Import QEMU upstream snapshot d2e570c
Upstream: https://gitlab.com/qemu-project/qemu.git Upstream-Commit: d2e570cc0f97b936902a5b1b86b73c0f5998b475
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
/* QEMU accelerator interfaces
|
||||
*
|
||||
* Copyright (c) 2014 Red Hat Inc
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef QEMU_ACCEL_H
|
||||
#define QEMU_ACCEL_H
|
||||
|
||||
#include "qom/object.h"
|
||||
#include "exec/hwaddr.h"
|
||||
|
||||
typedef struct AccelState AccelState;
|
||||
typedef struct AccelClass AccelClass;
|
||||
|
||||
#define TYPE_ACCEL "accel"
|
||||
|
||||
#define ACCEL_CLASS_SUFFIX "-" TYPE_ACCEL
|
||||
#define ACCEL_CLASS_NAME(a) (a ACCEL_CLASS_SUFFIX)
|
||||
|
||||
#define ACCEL_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(AccelClass, (klass), TYPE_ACCEL)
|
||||
#define ACCEL(obj) \
|
||||
OBJECT_CHECK(AccelState, (obj), TYPE_ACCEL)
|
||||
#define ACCEL_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(AccelClass, (obj), TYPE_ACCEL)
|
||||
|
||||
AccelClass *accel_find(const char *opt_name);
|
||||
AccelState *current_accel(void);
|
||||
const char *current_accel_name(void);
|
||||
|
||||
void accel_init_interfaces(AccelClass *ac);
|
||||
|
||||
int accel_init_machine(AccelState *accel, MachineState *ms);
|
||||
|
||||
/* Called just before os_setup_post (ie just before drop OS privs) */
|
||||
void accel_setup_post(MachineState *ms);
|
||||
|
||||
void accel_pre_resume(MachineState *ms, bool step_pending);
|
||||
|
||||
/**
|
||||
* accel_cpu_instance_init:
|
||||
* @cpu: The CPU that needs to do accel-specific object initializations.
|
||||
*/
|
||||
void accel_cpu_instance_init(CPUState *cpu);
|
||||
|
||||
/**
|
||||
* accel_cpu_common_realize:
|
||||
* @cpu: The CPU that needs to call accel-specific cpu realization.
|
||||
* @errp: currently unused.
|
||||
*/
|
||||
bool accel_cpu_common_realize(CPUState *cpu, Error **errp);
|
||||
|
||||
/**
|
||||
* accel_cpu_common_unrealize:
|
||||
* @cpu: The CPU that needs to call accel-specific cpu unrealization.
|
||||
*/
|
||||
void accel_cpu_common_unrealize(CPUState *cpu);
|
||||
|
||||
/**
|
||||
* struct AccelGdbConfig - gdbstub configuration for an accelerator.
|
||||
*
|
||||
* @sstep_flags: Set SSTEP_* flags that accelerator supports for guest debug.
|
||||
* @can_reverse: Whether reverse mode is supported.
|
||||
*/
|
||||
typedef struct AccelGdbConfig {
|
||||
unsigned sstep_flags;
|
||||
bool can_reverse;
|
||||
} AccelGdbConfig;
|
||||
|
||||
bool accel_supports_guest_debug(AccelState *accel);
|
||||
|
||||
#endif /* QEMU_ACCEL_H */
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* AioContext wait support
|
||||
*
|
||||
* Copyright (C) 2018 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_AIO_WAIT_H
|
||||
#define QEMU_AIO_WAIT_H
|
||||
|
||||
#include "qemu/aio.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
||||
/**
|
||||
* AioWait:
|
||||
*
|
||||
* An object that facilitates synchronous waiting on a condition. A single
|
||||
* global AioWait object (global_aio_wait) is used internally.
|
||||
*
|
||||
* The main loop can wait on an operation running in an IOThread as follows:
|
||||
*
|
||||
* AioContext *ctx = ...;
|
||||
* MyWork work = { .done = false };
|
||||
* schedule_my_work_in_iothread(ctx, &work);
|
||||
* AIO_WAIT_WHILE(ctx, !work.done);
|
||||
*
|
||||
* The IOThread must call aio_wait_kick() to notify the main loop when
|
||||
* work.done changes:
|
||||
*
|
||||
* static void do_work(...)
|
||||
* {
|
||||
* ...
|
||||
* work.done = true;
|
||||
* aio_wait_kick();
|
||||
* }
|
||||
*/
|
||||
typedef struct {
|
||||
/* Number of waiting AIO_WAIT_WHILE() callers. Accessed with atomic ops. */
|
||||
unsigned num_waiters;
|
||||
} AioWait;
|
||||
|
||||
extern AioWait global_aio_wait;
|
||||
|
||||
/**
|
||||
* AIO_WAIT_WHILE_INTERNAL:
|
||||
* @ctx: the aio context, or NULL if multiple aio contexts (for which the
|
||||
* caller does not hold a lock) are involved in the polling condition.
|
||||
* @cond: wait while this conditional expression is true
|
||||
*
|
||||
* Wait while a condition is true. Use this to implement synchronous
|
||||
* operations that require event loop activity.
|
||||
*
|
||||
* The caller must be sure that something calls aio_wait_kick() when the value
|
||||
* of @cond might have changed.
|
||||
*
|
||||
* The caller's thread must be the IOThread that owns @ctx or the main loop
|
||||
* thread (with @ctx acquired exactly once). This function cannot be used to
|
||||
* wait on conditions between two IOThreads since that could lead to deadlock,
|
||||
* go via the main loop instead.
|
||||
*/
|
||||
#define AIO_WAIT_WHILE_INTERNAL(ctx, cond) ({ \
|
||||
bool waited_ = false; \
|
||||
AioWait *wait_ = &global_aio_wait; \
|
||||
AioContext *ctx_ = (ctx); \
|
||||
/* Increment wait_->num_waiters before evaluating cond. */ \
|
||||
qatomic_inc(&wait_->num_waiters); \
|
||||
/* Paired with smp_mb in aio_wait_kick(). */ \
|
||||
smp_mb__after_rmw(); \
|
||||
if (ctx_ && in_aio_context_home_thread(ctx_)) { \
|
||||
while ((cond)) { \
|
||||
aio_poll(ctx_, true); \
|
||||
waited_ = true; \
|
||||
} \
|
||||
} else { \
|
||||
assert(qemu_get_current_aio_context() == \
|
||||
qemu_get_aio_context()); \
|
||||
while ((cond)) { \
|
||||
aio_poll(qemu_get_aio_context(), true); \
|
||||
waited_ = true; \
|
||||
} \
|
||||
} \
|
||||
qatomic_dec(&wait_->num_waiters); \
|
||||
waited_; })
|
||||
|
||||
#define AIO_WAIT_WHILE(ctx, cond) \
|
||||
AIO_WAIT_WHILE_INTERNAL(ctx, cond)
|
||||
|
||||
/* TODO replace this with AIO_WAIT_WHILE() in a future patch */
|
||||
#define AIO_WAIT_WHILE_UNLOCKED(ctx, cond) \
|
||||
AIO_WAIT_WHILE_INTERNAL(ctx, cond)
|
||||
|
||||
/**
|
||||
* aio_wait_kick:
|
||||
* Wake up the main thread if it is waiting on AIO_WAIT_WHILE(). During
|
||||
* synchronous operations performed in an IOThread, the main thread lets the
|
||||
* IOThread's event loop run, waiting for the operation to complete. A
|
||||
* aio_wait_kick() call will wake up the main thread.
|
||||
*/
|
||||
void aio_wait_kick(void);
|
||||
|
||||
/**
|
||||
* aio_wait_bh_oneshot:
|
||||
* @ctx: the aio context
|
||||
* @cb: the BH callback function
|
||||
* @opaque: user data for the BH callback function
|
||||
*
|
||||
* Run a BH in @ctx and wait for it to complete.
|
||||
*
|
||||
* Must be called from the main loop thread without @ctx acquired.
|
||||
* Note that main loop event processing may occur.
|
||||
*/
|
||||
void aio_wait_bh_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque);
|
||||
|
||||
/**
|
||||
* in_aio_context_home_thread:
|
||||
* @ctx: the aio context
|
||||
*
|
||||
* Return whether we are running in the thread that normally runs @ctx. Note
|
||||
* that acquiring/releasing ctx does not affect the outcome, each AioContext
|
||||
* still only has one home thread that is responsible for running it.
|
||||
*/
|
||||
static inline bool in_aio_context_home_thread(AioContext *ctx)
|
||||
{
|
||||
if (ctx == qemu_get_current_aio_context()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ctx == qemu_get_aio_context()) {
|
||||
return bql_locked();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* QEMU_AIO_WAIT_H */
|
||||
@@ -0,0 +1,855 @@
|
||||
/*
|
||||
* QEMU aio implementation
|
||||
*
|
||||
* Copyright IBM, Corp. 2008
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <[email protected]>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QEMU_AIO_H
|
||||
#define QEMU_AIO_H
|
||||
|
||||
#ifdef CONFIG_LINUX_IO_URING
|
||||
#include <liburing.h>
|
||||
#endif
|
||||
#include "qemu/coroutine-core.h"
|
||||
#include "qemu/queue.h"
|
||||
#include "qemu/event_notifier.h"
|
||||
#include "qemu/lockcnt.h"
|
||||
#include "qemu/thread.h"
|
||||
#include "qemu/timer.h"
|
||||
|
||||
struct MemReentrancyGuard;
|
||||
|
||||
typedef struct AioHandler AioHandler;
|
||||
typedef QLIST_HEAD(, AioHandler) AioHandlerList;
|
||||
typedef void QEMUBHFunc(void *opaque);
|
||||
typedef bool AioPollFn(void *opaque);
|
||||
typedef void IOHandler(void *opaque);
|
||||
|
||||
struct ThreadPoolAio;
|
||||
struct LinuxAioState;
|
||||
typedef struct LuringState LuringState;
|
||||
|
||||
/* Is polling disabled? */
|
||||
bool aio_poll_disabled(AioContext *ctx);
|
||||
|
||||
#ifdef CONFIG_LINUX_IO_URING
|
||||
/*
|
||||
* Each io_uring request must have a unique CqeHandler that processes the cqe.
|
||||
* The lifetime of a CqeHandler must be at least from aio_add_sqe() until
|
||||
* ->cb() invocation.
|
||||
*/
|
||||
typedef struct CqeHandler CqeHandler;
|
||||
struct CqeHandler {
|
||||
/* Called by the AioContext when the request has completed */
|
||||
void (*cb)(CqeHandler *handler);
|
||||
|
||||
/* Used internally, do not access this */
|
||||
QSIMPLEQ_ENTRY(CqeHandler) next;
|
||||
|
||||
/* This field is filled in before ->cb() is called */
|
||||
struct io_uring_cqe cqe;
|
||||
};
|
||||
|
||||
typedef QSIMPLEQ_HEAD(, CqeHandler) CqeHandlerSimpleQ;
|
||||
#endif /* CONFIG_LINUX_IO_URING */
|
||||
|
||||
/* Callbacks for file descriptor monitoring implementations */
|
||||
typedef struct {
|
||||
/*
|
||||
* update:
|
||||
* @ctx: the AioContext
|
||||
* @old_node: the existing handler or NULL if this file descriptor is being
|
||||
* monitored for the first time
|
||||
* @new_node: the new handler or NULL if this file descriptor is being
|
||||
* removed
|
||||
*
|
||||
* Add/remove/modify a monitored file descriptor.
|
||||
*
|
||||
* Called with ctx->list_lock acquired.
|
||||
*/
|
||||
void (*update)(AioContext *ctx, AioHandler *old_node, AioHandler *new_node);
|
||||
|
||||
/*
|
||||
* wait:
|
||||
* @ctx: the AioContext
|
||||
* @ready_list: list for handlers that become ready
|
||||
* @timeout: maximum duration to wait, in nanoseconds
|
||||
*
|
||||
* Wait for file descriptors to become ready and place them on ready_list.
|
||||
*
|
||||
* Called with ctx->list_lock incremented but not locked.
|
||||
*
|
||||
* Returns: number of ready file descriptors.
|
||||
*/
|
||||
int (*wait)(AioContext *ctx, AioHandlerList *ready_list, int64_t timeout);
|
||||
|
||||
/*
|
||||
* need_wait:
|
||||
* @ctx: the AioContext
|
||||
*
|
||||
* Tell aio_poll() when to stop userspace polling early because ->wait()
|
||||
* has fds ready.
|
||||
*
|
||||
* File descriptor monitoring implementations that cannot poll fd readiness
|
||||
* from userspace should use aio_poll_disabled() here. This ensures that
|
||||
* file descriptors are not starved by handlers that frequently make
|
||||
* progress via userspace polling.
|
||||
*
|
||||
* Returns: true if ->wait() should be called, false otherwise.
|
||||
*/
|
||||
bool (*need_wait)(AioContext *ctx);
|
||||
|
||||
/*
|
||||
* dispatch:
|
||||
* @ctx: the AioContext
|
||||
*
|
||||
* Dispatch any work that is specific to this file descriptor monitoring
|
||||
* implementation. Usually the event loop's generic file descriptor
|
||||
* monitoring, BH, and timer dispatching code is sufficient, but file
|
||||
* descriptor monitoring implementations offering additional functionality
|
||||
* may need to implement this function for custom behavior. Called at a
|
||||
* point in the event loop when it is safe to invoke user-defined
|
||||
* callbacks.
|
||||
*
|
||||
* This function is optional and may be NULL.
|
||||
*
|
||||
* Returns: true if progress was made (see aio_poll()'s return value),
|
||||
* false otherwise.
|
||||
*/
|
||||
bool (*dispatch)(AioContext *ctx);
|
||||
|
||||
/*
|
||||
* gsource_prepare:
|
||||
* @ctx: the AioContext
|
||||
*
|
||||
* Prepare for the glib event loop to wait for events instead of the usual
|
||||
* ->wait() call. See glib's GSourceFuncs->prepare().
|
||||
*/
|
||||
void (*gsource_prepare)(AioContext *ctx);
|
||||
|
||||
/*
|
||||
* gsource_check:
|
||||
* @ctx: the AioContext
|
||||
*
|
||||
* Called by the glib event loop from glib's GSourceFuncs->check() after
|
||||
* waiting for events.
|
||||
*
|
||||
* Returns: true when ready to be dispatched.
|
||||
*/
|
||||
bool (*gsource_check)(AioContext *ctx);
|
||||
|
||||
/*
|
||||
* gsource_dispatch:
|
||||
* @ctx: the AioContext
|
||||
* @ready_list: list for handlers that become ready
|
||||
*
|
||||
* Place ready AioHandlers on ready_list. Called as part of the glib event
|
||||
* loop from glib's GSourceFuncs->dispatch().
|
||||
*
|
||||
* Called with list_lock incremented.
|
||||
*/
|
||||
void (*gsource_dispatch)(AioContext *ctx, AioHandlerList *ready_list);
|
||||
|
||||
#ifdef CONFIG_LINUX_IO_URING
|
||||
/**
|
||||
* add_sqe: Add an io_uring sqe for submission.
|
||||
* @prep_sqe: invoked with an sqe that should be prepared for submission
|
||||
* @opaque: user-defined argument to @prep_sqe()
|
||||
* @cqe_handler: the unique cqe handler associated with this request
|
||||
*
|
||||
* The caller's @prep_sqe() function is invoked to fill in the details of
|
||||
* the sqe. Do not call io_uring_sqe_set_data() on this sqe.
|
||||
*
|
||||
* The kernel may see the sqe as soon as @prep_sqe() returns or it may take
|
||||
* until the next event loop iteration.
|
||||
*
|
||||
* This function is called from the current AioContext and is not
|
||||
* thread-safe.
|
||||
*/
|
||||
void (*add_sqe)(AioContext *ctx,
|
||||
void (*prep_sqe)(struct io_uring_sqe *sqe, void *opaque),
|
||||
void *opaque, CqeHandler *cqe_handler);
|
||||
#endif /* CONFIG_LINUX_IO_URING */
|
||||
} FDMonOps;
|
||||
|
||||
/*
|
||||
* Each aio_bh_poll() call carves off a slice of the BH list, so that newly
|
||||
* scheduled BHs are not processed until the next aio_bh_poll() call. All
|
||||
* active aio_bh_poll() calls chain their slices together in a list, so that
|
||||
* nested aio_bh_poll() calls process all scheduled bottom halves.
|
||||
*/
|
||||
typedef QSLIST_HEAD(, QEMUBH) BHList;
|
||||
typedef struct BHListSlice BHListSlice;
|
||||
struct BHListSlice {
|
||||
BHList bh_list;
|
||||
QSIMPLEQ_ENTRY(BHListSlice) next;
|
||||
};
|
||||
|
||||
typedef QSLIST_HEAD(, AioHandler) AioHandlerSList;
|
||||
|
||||
typedef struct AioPolledEvent {
|
||||
int64_t ns; /* estimated block time in nanoseconds */
|
||||
} AioPolledEvent;
|
||||
|
||||
struct AioContext {
|
||||
GSource source;
|
||||
|
||||
/* Used by AioContext users to protect from multi-threaded access. */
|
||||
QemuRecMutex lock;
|
||||
|
||||
/*
|
||||
* Keep track of readers and writers of the block layer graph.
|
||||
* This is essential to avoid performing additions and removal
|
||||
* of nodes and edges from block graph while some
|
||||
* other thread is traversing it.
|
||||
*/
|
||||
struct BdrvGraphRWlock *bdrv_graph;
|
||||
|
||||
/* The list of registered AIO handlers. Protected by ctx->list_lock. */
|
||||
AioHandlerList aio_handlers;
|
||||
|
||||
/* The list of AIO handlers to be deleted. Protected by ctx->list_lock. */
|
||||
AioHandlerList deleted_aio_handlers;
|
||||
|
||||
/* Used to avoid unnecessary event_notifier_set calls in aio_notify;
|
||||
* only written from the AioContext home thread, or under the BQL in
|
||||
* the case of the main AioContext. However, it is read from any
|
||||
* thread so it is still accessed with atomic primitives.
|
||||
*
|
||||
* If this field is 0, everything (file descriptors, bottom halves,
|
||||
* timers) will be re-evaluated before the next blocking poll() or
|
||||
* io_uring wait; therefore, the event_notifier_set call can be
|
||||
* skipped. If it is non-zero, you may need to wake up a concurrent
|
||||
* aio_poll or the glib main event loop, making event_notifier_set
|
||||
* necessary.
|
||||
*
|
||||
* Bit 0 is reserved for GSource usage of the AioContext, and is 1
|
||||
* between a call to aio_ctx_prepare and the next call to aio_ctx_check.
|
||||
* Bits 1-31 simply count the number of active calls to aio_poll
|
||||
* that are in the prepare or poll phase.
|
||||
*
|
||||
* The GSource and aio_poll must use a different mechanism because
|
||||
* there is no certainty that a call to GSource's prepare callback
|
||||
* (via g_main_context_prepare) is indeed followed by check and
|
||||
* dispatch. It's not clear whether this would be a bug, but let's
|
||||
* play safe and allow it---it will just cause extra calls to
|
||||
* event_notifier_set until the next call to dispatch.
|
||||
*
|
||||
* Instead, the aio_poll calls include both the prepare and the
|
||||
* dispatch phase, hence a simple counter is enough for them.
|
||||
*/
|
||||
uint32_t notify_me;
|
||||
|
||||
/* A lock to protect between QEMUBH and AioHandler adders and deleter,
|
||||
* and to ensure that no callbacks are removed while we're walking and
|
||||
* dispatching them.
|
||||
*/
|
||||
QemuLockCnt list_lock;
|
||||
|
||||
/* Bottom Halves pending aio_bh_poll() processing */
|
||||
BHList bh_list;
|
||||
|
||||
/* Chained BH list slices for each nested aio_bh_poll() call */
|
||||
QSIMPLEQ_HEAD(, BHListSlice) bh_slice_list;
|
||||
|
||||
/* Used by aio_notify.
|
||||
*
|
||||
* "notified" is used to avoid expensive event_notifier_test_and_clear
|
||||
* calls. When it is clear, the EventNotifier is clear, or one thread
|
||||
* is going to clear "notified" before processing more events. False
|
||||
* positives are possible, i.e. "notified" could be set even though the
|
||||
* EventNotifier is clear.
|
||||
*
|
||||
* Note that event_notifier_set *cannot* be optimized the same way. For
|
||||
* more information on the problem that would result, see "#ifdef BUG2"
|
||||
* in the docs/aio_notify_accept.promela formal model.
|
||||
*/
|
||||
bool notified;
|
||||
EventNotifier notifier;
|
||||
|
||||
QSLIST_HEAD(, Coroutine) scheduled_coroutines;
|
||||
QEMUBH *co_schedule_bh;
|
||||
|
||||
int thread_pool_min;
|
||||
int thread_pool_max;
|
||||
/* Thread pool for performing work and receiving completion callbacks.
|
||||
* Has its own locking.
|
||||
*/
|
||||
struct ThreadPoolAio *thread_pool;
|
||||
|
||||
#ifdef CONFIG_LINUX_AIO
|
||||
struct LinuxAioState *linux_aio;
|
||||
#endif
|
||||
#ifdef CONFIG_LINUX_IO_URING
|
||||
/* State for file descriptor monitoring using Linux io_uring */
|
||||
struct io_uring fdmon_io_uring;
|
||||
AioHandlerSList submit_list;
|
||||
void *io_uring_fd_tag;
|
||||
|
||||
/* Pending callback state for cqe handlers */
|
||||
CqeHandlerSimpleQ cqe_handler_ready_list;
|
||||
#endif /* CONFIG_LINUX_IO_URING */
|
||||
|
||||
/* TimerLists for calling timers - one per clock type. Has its own
|
||||
* locking.
|
||||
*/
|
||||
QEMUTimerListGroup tlg;
|
||||
|
||||
/* Number of AioHandlers without .io_poll() */
|
||||
int poll_disable_cnt;
|
||||
|
||||
/* Polling mode parameters */
|
||||
int64_t poll_ns; /* current polling time in nanoseconds */
|
||||
int64_t poll_max_ns; /* maximum polling time in nanoseconds */
|
||||
int64_t poll_grow; /* polling time growth factor */
|
||||
int64_t poll_shrink; /* polling time shrink factor */
|
||||
int64_t poll_weight; /* weight of current interval in calculation */
|
||||
|
||||
/* AIO engine parameters */
|
||||
int64_t aio_max_batch; /* maximum number of requests in a batch */
|
||||
|
||||
/*
|
||||
* List of handlers participating in userspace polling. Protected by
|
||||
* ctx->list_lock. Iterated and modified mostly by the event loop thread
|
||||
* from aio_poll() with ctx->list_lock incremented. aio_set_fd_handler()
|
||||
* only touches the list to delete nodes if ctx->list_lock's count is zero.
|
||||
*/
|
||||
AioHandlerList poll_aio_handlers;
|
||||
|
||||
/* Are we in polling mode or monitoring file descriptors? */
|
||||
bool poll_started;
|
||||
|
||||
/* epoll(7) state used when built with CONFIG_EPOLL */
|
||||
int epollfd;
|
||||
|
||||
/* The GSource unix fd tag for epollfd */
|
||||
void *epollfd_tag;
|
||||
|
||||
const FDMonOps *fdmon_ops;
|
||||
|
||||
/* Was aio_context_new() successful? */
|
||||
bool initialized;
|
||||
};
|
||||
|
||||
/**
|
||||
* aio_context_new: Allocate a new AioContext.
|
||||
*
|
||||
* AioContext provide a mini event-loop that can be waited on synchronously.
|
||||
* They also provide bottom halves, a service to execute a piece of code
|
||||
* as soon as possible.
|
||||
*/
|
||||
AioContext *aio_context_new(Error **errp);
|
||||
|
||||
/**
|
||||
* aio_context_ref:
|
||||
* @ctx: The AioContext to operate on.
|
||||
*
|
||||
* Add a reference to an AioContext.
|
||||
*/
|
||||
void aio_context_ref(AioContext *ctx);
|
||||
|
||||
/**
|
||||
* aio_context_unref:
|
||||
* @ctx: The AioContext to operate on.
|
||||
*
|
||||
* Drop a reference to an AioContext.
|
||||
*/
|
||||
void aio_context_unref(AioContext *ctx);
|
||||
|
||||
/**
|
||||
* aio_bh_schedule_oneshot_full: Allocate a new bottom half structure that will
|
||||
* run only once and as soon as possible.
|
||||
*
|
||||
* @name: A human-readable identifier for debugging purposes.
|
||||
*/
|
||||
void aio_bh_schedule_oneshot_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque,
|
||||
const char *name);
|
||||
|
||||
/**
|
||||
* aio_bh_schedule_oneshot: Allocate a new bottom half structure that will run
|
||||
* only once and as soon as possible.
|
||||
*
|
||||
* A convenience wrapper for aio_bh_schedule_oneshot_full() that uses cb as the
|
||||
* name string.
|
||||
*/
|
||||
#define aio_bh_schedule_oneshot(ctx, cb, opaque) \
|
||||
aio_bh_schedule_oneshot_full((ctx), (cb), (opaque), (stringify(cb)))
|
||||
|
||||
/**
|
||||
* aio_bh_new_full: Allocate a new bottom half structure.
|
||||
*
|
||||
* Bottom halves are lightweight callbacks whose invocation is guaranteed
|
||||
* to be wait-free, thread-safe and signal-safe. The #QEMUBH structure
|
||||
* is opaque and must be allocated prior to its use.
|
||||
*
|
||||
* @name: A human-readable identifier for debugging purposes.
|
||||
* @reentrancy_guard: A guard set when entering a cb to prevent
|
||||
* device-reentrancy issues
|
||||
*/
|
||||
QEMUBH *aio_bh_new_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque,
|
||||
const char *name, struct MemReentrancyGuard *reentrancy_guard);
|
||||
|
||||
/**
|
||||
* aio_bh_new: Allocate a new bottom half structure
|
||||
*
|
||||
* A convenience wrapper for aio_bh_new_full() that uses the cb as the name
|
||||
* string.
|
||||
*/
|
||||
#define aio_bh_new(ctx, cb, opaque) \
|
||||
aio_bh_new_full((ctx), (cb), (opaque), (stringify(cb)), NULL)
|
||||
|
||||
/**
|
||||
* aio_bh_new_guarded: Allocate a new bottom half structure with a
|
||||
* reentrancy_guard
|
||||
*
|
||||
* A convenience wrapper for aio_bh_new_full() that uses the cb as the name
|
||||
* string.
|
||||
*/
|
||||
#define aio_bh_new_guarded(ctx, cb, opaque, guard) \
|
||||
aio_bh_new_full((ctx), (cb), (opaque), (stringify(cb)), guard)
|
||||
|
||||
/**
|
||||
* aio_notify: Force processing of pending events.
|
||||
*
|
||||
* Similar to signaling a condition variable, aio_notify forces
|
||||
* aio_poll to exit, so that the next call will re-examine pending events.
|
||||
* The caller of aio_notify will usually call aio_poll again very soon,
|
||||
* or go through another iteration of the GLib main loop. Hence, aio_notify
|
||||
* also has the side effect of recalculating the sets of file descriptors
|
||||
* that the main loop waits for.
|
||||
*
|
||||
* Calling aio_notify is rarely necessary, because for example scheduling
|
||||
* a bottom half calls it already.
|
||||
*/
|
||||
void aio_notify(AioContext *ctx);
|
||||
|
||||
/**
|
||||
* aio_notify_accept: Acknowledge receiving an aio_notify.
|
||||
*
|
||||
* aio_notify() uses an EventNotifier in order to wake up a sleeping
|
||||
* aio_poll() or g_main_context_iteration(). Calls to aio_notify() are
|
||||
* usually rare, but the AioContext has to clear the EventNotifier on
|
||||
* every aio_poll() or g_main_context_iteration() in order to avoid
|
||||
* busy waiting. This event_notifier_test_and_clear() cannot be done
|
||||
* using the usual aio_context_set_event_notifier(), because it must
|
||||
* be done before processing all events (file descriptors, bottom halves,
|
||||
* timers).
|
||||
*
|
||||
* aio_notify_accept() is an optimized event_notifier_test_and_clear()
|
||||
* that is specific to an AioContext's notifier; it is used internally
|
||||
* to clear the EventNotifier only if aio_notify() had been called.
|
||||
*/
|
||||
void aio_notify_accept(AioContext *ctx);
|
||||
|
||||
/**
|
||||
* aio_bh_call: Executes callback function of the specified BH.
|
||||
*/
|
||||
void aio_bh_call(QEMUBH *bh);
|
||||
|
||||
/**
|
||||
* aio_bh_poll: Poll bottom halves for an AioContext.
|
||||
*
|
||||
* These are internal functions used by the QEMU main loop.
|
||||
* And notice that multiple occurrences of aio_bh_poll cannot
|
||||
* be called concurrently
|
||||
*/
|
||||
int aio_bh_poll(AioContext *ctx);
|
||||
|
||||
/**
|
||||
* qemu_bh_schedule: Schedule a bottom half.
|
||||
*
|
||||
* Scheduling a bottom half interrupts the main loop and causes the
|
||||
* execution of the callback that was passed to qemu_bh_new.
|
||||
*
|
||||
* Bottom halves that are scheduled from a bottom half handler are instantly
|
||||
* invoked. This can create an infinite loop if a bottom half handler
|
||||
* schedules itself.
|
||||
*
|
||||
* @bh: The bottom half to be scheduled.
|
||||
*/
|
||||
void qemu_bh_schedule(QEMUBH *bh);
|
||||
|
||||
/**
|
||||
* qemu_bh_cancel: Cancel execution of a bottom half.
|
||||
*
|
||||
* Canceling execution of a bottom half undoes the effect of calls to
|
||||
* qemu_bh_schedule without freeing its resources yet. While cancellation
|
||||
* itself is also wait-free and thread-safe, it can of course race with the
|
||||
* loop that executes bottom halves unless you are holding the iothread
|
||||
* mutex. This makes it mostly useless if you are not holding the mutex.
|
||||
*
|
||||
* @bh: The bottom half to be canceled.
|
||||
*/
|
||||
void qemu_bh_cancel(QEMUBH *bh);
|
||||
|
||||
/**
|
||||
*qemu_bh_delete: Cancel execution of a bottom half and free its resources.
|
||||
*
|
||||
* Deleting a bottom half frees the memory that was allocated for it by
|
||||
* qemu_bh_new. It also implies canceling the bottom half if it was
|
||||
* scheduled.
|
||||
* This func is async. The bottom half will do the delete action at the finial
|
||||
* end.
|
||||
*
|
||||
* @bh: The bottom half to be deleted.
|
||||
*/
|
||||
void qemu_bh_delete(QEMUBH *bh);
|
||||
|
||||
/* Return whether there are any pending callbacks from the GSource
|
||||
* attached to the AioContext, before g_poll is invoked.
|
||||
*
|
||||
* This is used internally in the implementation of the GSource.
|
||||
*/
|
||||
bool aio_prepare(AioContext *ctx);
|
||||
|
||||
/* Return whether there are any pending callbacks from the GSource
|
||||
* attached to the AioContext, after g_poll is invoked.
|
||||
*
|
||||
* This is used internally in the implementation of the GSource.
|
||||
*/
|
||||
bool aio_pending(AioContext *ctx);
|
||||
|
||||
/* Dispatch any pending callbacks from the GSource attached to the AioContext.
|
||||
*
|
||||
* This is used internally in the implementation of the GSource.
|
||||
*/
|
||||
void aio_dispatch(AioContext *ctx);
|
||||
|
||||
/* Progress in completing AIO work to occur. This can issue new pending
|
||||
* aio as a result of executing I/O completion or bh callbacks.
|
||||
*
|
||||
* Return whether any progress was made by executing AIO or bottom half
|
||||
* handlers. If @blocking == true, this should always be true except
|
||||
* if someone called aio_notify.
|
||||
*
|
||||
* If there are no pending bottom halves, but there are pending AIO
|
||||
* operations, it may not be possible to make any progress without
|
||||
* blocking. If @blocking is true, this function will wait until one
|
||||
* or more AIO events have completed, to ensure something has moved
|
||||
* before returning.
|
||||
*/
|
||||
bool no_coroutine_fn aio_poll(AioContext *ctx, bool blocking);
|
||||
|
||||
/* Register a file descriptor and associated callbacks. Behaves very similarly
|
||||
* to qemu_set_fd_handler. Unlike qemu_set_fd_handler, these callbacks will
|
||||
* be invoked when using aio_poll().
|
||||
*
|
||||
* Code that invokes AIO completion functions should rely on this function
|
||||
* instead of qemu_set_fd_handler[2].
|
||||
*/
|
||||
void aio_set_fd_handler(AioContext *ctx,
|
||||
int fd,
|
||||
IOHandler *io_read,
|
||||
IOHandler *io_write,
|
||||
AioPollFn *io_poll,
|
||||
IOHandler *io_poll_ready,
|
||||
void *opaque);
|
||||
|
||||
/* Register an event notifier and associated callbacks. Behaves very similarly
|
||||
* to event_notifier_set_handler. Unlike event_notifier_set_handler, these callbacks
|
||||
* will be invoked when using aio_poll().
|
||||
*
|
||||
* Code that invokes AIO completion functions should rely on this function
|
||||
* instead of event_notifier_set_handler.
|
||||
*/
|
||||
void aio_set_event_notifier(AioContext *ctx,
|
||||
EventNotifier *notifier,
|
||||
EventNotifierHandler *io_read,
|
||||
AioPollFn *io_poll,
|
||||
EventNotifierHandler *io_poll_ready);
|
||||
|
||||
/*
|
||||
* Set polling begin/end callbacks for an event notifier that has already been
|
||||
* registered with aio_set_event_notifier. Do nothing if the event notifier is
|
||||
* not registered.
|
||||
*
|
||||
* Note that if the io_poll_end() callback (or the entire notifier) is removed
|
||||
* during polling, it will not be called, so an io_poll_begin() is not
|
||||
* necessarily always followed by an io_poll_end().
|
||||
*/
|
||||
void aio_set_event_notifier_poll(AioContext *ctx,
|
||||
EventNotifier *notifier,
|
||||
EventNotifierHandler *io_poll_begin,
|
||||
EventNotifierHandler *io_poll_end);
|
||||
|
||||
/* Return a GSource that lets the main loop poll the file descriptors attached
|
||||
* to this AioContext.
|
||||
*/
|
||||
GSource *aio_get_g_source(AioContext *ctx);
|
||||
|
||||
/* Return the ThreadPoolAio bound to this AioContext */
|
||||
struct ThreadPoolAio *aio_get_thread_pool(AioContext *ctx);
|
||||
|
||||
/* Setup the LinuxAioState bound to this AioContext */
|
||||
struct LinuxAioState *aio_setup_linux_aio(AioContext *ctx, Error **errp);
|
||||
|
||||
/* Return the LinuxAioState bound to this AioContext */
|
||||
struct LinuxAioState *aio_get_linux_aio(AioContext *ctx);
|
||||
|
||||
/**
|
||||
* aio_timer_new_with_attrs:
|
||||
* @ctx: the aio context
|
||||
* @type: the clock type
|
||||
* @scale: the scale
|
||||
* @attributes: 0, or one to multiple OR'ed QEMU_TIMER_ATTR_<id> values
|
||||
* to assign
|
||||
* @cb: the callback to call on timer expiry
|
||||
* @opaque: the opaque pointer to pass to the callback
|
||||
*
|
||||
* Allocate a new timer (with attributes) attached to the context @ctx.
|
||||
* The function is responsible for memory allocation.
|
||||
*
|
||||
* The preferred interface is aio_timer_init or aio_timer_init_with_attrs.
|
||||
* Use that unless you really need dynamic memory allocation.
|
||||
*
|
||||
* Returns: a pointer to the new timer
|
||||
*/
|
||||
static inline QEMUTimer *aio_timer_new_with_attrs(AioContext *ctx,
|
||||
QEMUClockType type,
|
||||
int scale, int attributes,
|
||||
QEMUTimerCB *cb, void *opaque)
|
||||
{
|
||||
return timer_new_full(&ctx->tlg, type, scale, attributes, cb, opaque);
|
||||
}
|
||||
|
||||
/**
|
||||
* aio_timer_new:
|
||||
* @ctx: the aio context
|
||||
* @type: the clock type
|
||||
* @scale: the scale
|
||||
* @cb: the callback to call on timer expiry
|
||||
* @opaque: the opaque pointer to pass to the callback
|
||||
*
|
||||
* Allocate a new timer attached to the context @ctx.
|
||||
* See aio_timer_new_with_attrs for details.
|
||||
*
|
||||
* Returns: a pointer to the new timer
|
||||
*/
|
||||
static inline QEMUTimer *aio_timer_new(AioContext *ctx, QEMUClockType type,
|
||||
int scale,
|
||||
QEMUTimerCB *cb, void *opaque)
|
||||
{
|
||||
return timer_new_full(&ctx->tlg, type, scale, 0, cb, opaque);
|
||||
}
|
||||
|
||||
/**
|
||||
* aio_timer_init_with_attrs:
|
||||
* @ctx: the aio context
|
||||
* @ts: the timer
|
||||
* @type: the clock type
|
||||
* @scale: the scale
|
||||
* @attributes: 0, or one to multiple OR'ed QEMU_TIMER_ATTR_<id> values
|
||||
* to assign
|
||||
* @cb: the callback to call on timer expiry
|
||||
* @opaque: the opaque pointer to pass to the callback
|
||||
*
|
||||
* Initialise a new timer (with attributes) attached to the context @ctx.
|
||||
* The caller is responsible for memory allocation.
|
||||
*/
|
||||
static inline void aio_timer_init_with_attrs(AioContext *ctx,
|
||||
QEMUTimer *ts, QEMUClockType type,
|
||||
int scale, int attributes,
|
||||
QEMUTimerCB *cb, void *opaque)
|
||||
{
|
||||
timer_init_full(ts, &ctx->tlg, type, scale, attributes, cb, opaque);
|
||||
}
|
||||
|
||||
/**
|
||||
* aio_timer_init:
|
||||
* @ctx: the aio context
|
||||
* @ts: the timer
|
||||
* @type: the clock type
|
||||
* @scale: the scale
|
||||
* @cb: the callback to call on timer expiry
|
||||
* @opaque: the opaque pointer to pass to the callback
|
||||
*
|
||||
* Initialise a new timer attached to the context @ctx.
|
||||
* See aio_timer_init_with_attrs for details.
|
||||
*/
|
||||
static inline void aio_timer_init(AioContext *ctx,
|
||||
QEMUTimer *ts, QEMUClockType type,
|
||||
int scale,
|
||||
QEMUTimerCB *cb, void *opaque)
|
||||
{
|
||||
timer_init_full(ts, &ctx->tlg, type, scale, 0, cb, opaque);
|
||||
}
|
||||
|
||||
/**
|
||||
* aio_compute_timeout:
|
||||
* @ctx: the aio context
|
||||
*
|
||||
* Compute the timeout that a blocking aio_poll should use.
|
||||
*/
|
||||
int64_t aio_compute_timeout(AioContext *ctx);
|
||||
|
||||
/**
|
||||
* aio_co_schedule:
|
||||
* @ctx: the aio context
|
||||
* @co: the coroutine
|
||||
*
|
||||
* Start a coroutine on a remote AioContext.
|
||||
*
|
||||
* The coroutine must not be entered by anyone else while aio_co_schedule()
|
||||
* is active. In addition the coroutine must have yielded unless ctx
|
||||
* is the context in which the coroutine is running (i.e. the value of
|
||||
* qemu_get_current_aio_context() from the coroutine itself).
|
||||
*/
|
||||
void aio_co_schedule(AioContext *ctx, Coroutine *co);
|
||||
|
||||
/**
|
||||
* aio_co_reschedule_self:
|
||||
* @new_ctx: the new context
|
||||
*
|
||||
* Move the currently running coroutine to new_ctx. If the coroutine is already
|
||||
* running in new_ctx, do nothing.
|
||||
*
|
||||
* Note that this function cannot reschedule from iohandler_ctx to
|
||||
* qemu_aio_context.
|
||||
*/
|
||||
void coroutine_fn aio_co_reschedule_self(AioContext *new_ctx);
|
||||
|
||||
/**
|
||||
* aio_co_wake:
|
||||
* @co: the coroutine
|
||||
*
|
||||
* Restart a coroutine on the AioContext where it was running last, thus
|
||||
* preventing coroutines from jumping from one context to another when they
|
||||
* go to sleep.
|
||||
*
|
||||
* aio_co_wake may be executed either in coroutine or non-coroutine
|
||||
* context. The coroutine must not be entered by anyone else while
|
||||
* aio_co_wake() is active.
|
||||
*
|
||||
* If `co`'s AioContext differs from the current AioContext, this will call
|
||||
* aio_co_schedule(), which makes this safe to use even when `co` has not
|
||||
* yielded yet. In such a case, it will be entered once it yields.
|
||||
*
|
||||
* In contrast, if `co`'s AioContext is equal to the current one, it is
|
||||
* required for `co` to currently be yielding. This is generally the case
|
||||
* if the caller is not in `co` (i.e. invoked by `co`), because the only
|
||||
* other way for the caller to be running then is for `co` to currently be
|
||||
* yielding.
|
||||
*
|
||||
* Therefore, if there is no way for the caller to be invoked/entered by
|
||||
* `co`, it is generally safe to call this regardless of whether `co` is
|
||||
* known to already be yielding or not -- it only has to yield at some
|
||||
* point.
|
||||
*/
|
||||
void aio_co_wake(Coroutine *co);
|
||||
|
||||
/**
|
||||
* aio_co_enter:
|
||||
* @ctx: the context to run the coroutine
|
||||
* @co: the coroutine to run
|
||||
*
|
||||
* Enter a coroutine in the specified AioContext.
|
||||
*/
|
||||
void aio_co_enter(AioContext *ctx, Coroutine *co);
|
||||
|
||||
/**
|
||||
* Return the AioContext whose event loop runs in the current thread.
|
||||
*
|
||||
* If called from an IOThread this will be the IOThread's AioContext. If
|
||||
* called from the main thread or with the "big QEMU lock" taken it
|
||||
* will be the main loop AioContext.
|
||||
*
|
||||
* Note that the return value is never the main loop's iohandler_ctx and the
|
||||
* return value is the main loop AioContext instead.
|
||||
*/
|
||||
AioContext *qemu_get_current_aio_context(void);
|
||||
|
||||
void qemu_set_current_aio_context(AioContext *ctx);
|
||||
|
||||
/**
|
||||
* aio_context_setup:
|
||||
* @ctx: the aio context
|
||||
* @errp: error pointer
|
||||
*
|
||||
* Initialize the aio context.
|
||||
*
|
||||
* Returns: true on success, false otherwise
|
||||
*/
|
||||
bool aio_context_setup(AioContext *ctx, Error **errp);
|
||||
|
||||
/**
|
||||
* aio_context_destroy:
|
||||
* @ctx: the aio context
|
||||
*
|
||||
* Destroy the aio context.
|
||||
*/
|
||||
void aio_context_destroy(AioContext *ctx);
|
||||
|
||||
/**
|
||||
* aio_context_set_poll_params:
|
||||
* @ctx: the aio context
|
||||
* @max_ns: how long to busy poll for, in nanoseconds
|
||||
* @grow: polling time growth factor
|
||||
* @shrink: polling time shrink factor
|
||||
* @weight: weight factor applied to the current polling interval
|
||||
*
|
||||
* Poll mode can be disabled by setting poll_max_ns to 0.
|
||||
*/
|
||||
void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns,
|
||||
int64_t grow, int64_t shrink,
|
||||
int64_t weight, Error **errp);
|
||||
|
||||
/**
|
||||
* aio_context_set_aio_params:
|
||||
* @ctx: the aio context
|
||||
* @max_batch: maximum number of requests in a batch, 0 means that the
|
||||
* engine will use its default
|
||||
*/
|
||||
void aio_context_set_aio_params(AioContext *ctx, int64_t max_batch);
|
||||
|
||||
/**
|
||||
* aio_context_set_thread_pool_params:
|
||||
* @ctx: the aio context
|
||||
* @min: min number of threads to have readily available in the thread pool
|
||||
* @min: max number of threads the thread pool can contain
|
||||
*/
|
||||
void aio_context_set_thread_pool_params(AioContext *ctx, int64_t min,
|
||||
int64_t max, Error **errp);
|
||||
|
||||
#ifdef CONFIG_LINUX_IO_URING
|
||||
/**
|
||||
* aio_has_io_uring: Return whether io_uring is available.
|
||||
*
|
||||
* io_uring is either available in all AioContexts or in none, so this only
|
||||
* needs to be called once from within any thread's AioContext.
|
||||
*/
|
||||
static inline bool aio_has_io_uring(void)
|
||||
{
|
||||
AioContext *ctx = qemu_get_current_aio_context();
|
||||
return ctx->fdmon_ops->add_sqe;
|
||||
}
|
||||
|
||||
/**
|
||||
* aio_add_sqe: Add an io_uring sqe for submission.
|
||||
* @prep_sqe: invoked with an sqe that should be prepared for submission
|
||||
* @opaque: user-defined argument to @prep_sqe()
|
||||
* @cqe_handler: the unique cqe handler associated with this request
|
||||
*
|
||||
* The caller's @prep_sqe() function is invoked to fill in the details of the
|
||||
* sqe. Do not call io_uring_sqe_set_data() on this sqe.
|
||||
*
|
||||
* The sqe is submitted by the current AioContext. The kernel may see the sqe
|
||||
* as soon as @prep_sqe() returns or it may take until the next event loop
|
||||
* iteration.
|
||||
*
|
||||
* When the AioContext is destroyed, pending sqes are ignored and their
|
||||
* CqeHandlers are not invoked.
|
||||
*
|
||||
* This function must be called only when aio_has_io_uring() returns true.
|
||||
*/
|
||||
void aio_add_sqe(void (*prep_sqe)(struct io_uring_sqe *sqe, void *opaque),
|
||||
void *opaque, CqeHandler *cqe_handler);
|
||||
#endif /* CONFIG_LINUX_IO_URING */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Data structures representing asynchronous I/O operations
|
||||
*
|
||||
* Copyright IBM, Corp. 2008
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <[email protected]>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QEMU_AIOCB_H
|
||||
#define QEMU_AIOCB_H
|
||||
|
||||
typedef struct BlockAIOCB BlockAIOCB;
|
||||
typedef void BlockCompletionFunc(void *opaque, int ret);
|
||||
|
||||
typedef struct AIOCBInfo {
|
||||
void (*cancel_async)(BlockAIOCB *acb);
|
||||
size_t aiocb_size;
|
||||
} AIOCBInfo;
|
||||
|
||||
struct BlockAIOCB {
|
||||
const AIOCBInfo *aiocb_info;
|
||||
BlockDriverState *bs;
|
||||
BlockCompletionFunc *cb;
|
||||
void *opaque;
|
||||
int refcnt;
|
||||
};
|
||||
|
||||
void *qemu_aio_get(const AIOCBInfo *aiocb_info, BlockDriverState *bs,
|
||||
BlockCompletionFunc *cb, void *opaque);
|
||||
void qemu_aio_unref(void *p);
|
||||
void qemu_aio_ref(void *p);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Asynchronous teardown
|
||||
*
|
||||
* Copyright IBM, Corp. 2022
|
||||
*
|
||||
* Authors:
|
||||
* Claudio Imbrenda <[email protected]>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or (at your
|
||||
* option) any later version. See the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
#ifndef QEMU_ASYNC_TEARDOWN_H
|
||||
#define QEMU_ASYNC_TEARDOWN_H
|
||||
|
||||
#ifdef CONFIG_LINUX
|
||||
void init_async_teardown(void);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Simple interface for atomic operations.
|
||||
*
|
||||
* Copyright (C) 2013 Red Hat, Inc.
|
||||
*
|
||||
* Author: Paolo Bonzini <[email protected]>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
* See docs/devel/atomics.rst for discussion about the guarantees each
|
||||
* atomic primitive is meant to provide.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_ATOMIC_H
|
||||
#define QEMU_ATOMIC_H
|
||||
|
||||
#include "compiler.h"
|
||||
|
||||
/* Compiler barrier */
|
||||
#define barrier() ({ asm volatile("" ::: "memory"); (void)0; })
|
||||
|
||||
#ifndef __ATOMIC_RELAXED
|
||||
#error "Expecting C11 atomic ops"
|
||||
#endif
|
||||
|
||||
/* Manual memory barriers
|
||||
*
|
||||
*__atomic_thread_fence does not include a compiler barrier; instead,
|
||||
* the barrier is part of __atomic_load/__atomic_store's "volatile-like"
|
||||
* semantics. If smp_wmb() is a no-op, absence of the barrier means that
|
||||
* the compiler is free to reorder stores on each side of the barrier.
|
||||
* Add one here, and similarly in smp_rmb() and smp_read_barrier_depends().
|
||||
*/
|
||||
|
||||
#define smp_mb() ({ barrier(); __atomic_thread_fence(__ATOMIC_SEQ_CST); })
|
||||
#define smp_mb_release() ({ barrier(); __atomic_thread_fence(__ATOMIC_RELEASE); })
|
||||
#define smp_mb_acquire() ({ barrier(); __atomic_thread_fence(__ATOMIC_ACQUIRE); })
|
||||
|
||||
/* Most compilers currently treat consume and acquire the same, but really
|
||||
* no processors except Alpha need a barrier here. Leave it in if
|
||||
* using Thread Sanitizer to avoid warnings, otherwise optimize it away.
|
||||
*/
|
||||
#ifdef QEMU_SANITIZE_THREAD
|
||||
#define smp_read_barrier_depends() ({ barrier(); __atomic_thread_fence(__ATOMIC_CONSUME); })
|
||||
#elif defined(__alpha__)
|
||||
#define smp_read_barrier_depends() asm volatile("mb":::"memory")
|
||||
#else
|
||||
#define smp_read_barrier_depends() barrier()
|
||||
#endif
|
||||
|
||||
/*
|
||||
* A signal barrier forces all pending local memory ops to be observed before
|
||||
* a SIGSEGV is delivered to the *same* thread. In practice this is exactly
|
||||
* the same as barrier(), but since we have the correct builtin, use it.
|
||||
*/
|
||||
#define signal_barrier() __atomic_signal_fence(__ATOMIC_SEQ_CST)
|
||||
|
||||
/*
|
||||
* Sanity check that the size of an atomic operation isn't "overly large".
|
||||
* Despite the fact that e.g. x86-64 has 128-bit atomic operations, we do not
|
||||
* want to use them because we ought not need them, and this lets us do a
|
||||
* bit of sanity checking that other 32- and 64-bit hosts might build.
|
||||
*/
|
||||
#define ATOMIC_REG_SIZE sizeof(uint64_t)
|
||||
|
||||
/* Weak atomic operations prevent the compiler moving other
|
||||
* loads/stores past the atomic operation load/store. However there is
|
||||
* no explicit memory barrier for the processor.
|
||||
*
|
||||
* The C11 memory model says that variables that are accessed from
|
||||
* different threads should at least be done with __ATOMIC_RELAXED
|
||||
* primitives or the result is undefined. Generally this has little to
|
||||
* no effect on the generated code but not using the atomic primitives
|
||||
* will get flagged by sanitizers as a violation.
|
||||
*/
|
||||
#define qatomic_read__nocheck(ptr) \
|
||||
__atomic_load_n(ptr, __ATOMIC_RELAXED)
|
||||
|
||||
#define qatomic_read(ptr) \
|
||||
({ \
|
||||
qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \
|
||||
qatomic_read__nocheck(ptr); \
|
||||
})
|
||||
|
||||
#define qatomic_set__nocheck(ptr, i) \
|
||||
__atomic_store_n(ptr, i, __ATOMIC_RELAXED)
|
||||
|
||||
#define qatomic_set(ptr, i) do { \
|
||||
qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \
|
||||
qatomic_set__nocheck(ptr, i); \
|
||||
} while(0)
|
||||
|
||||
/* See above: most compilers currently treat consume and acquire the
|
||||
* same, but this slows down qatomic_rcu_read unnecessarily.
|
||||
*/
|
||||
#ifdef QEMU_SANITIZE_THREAD
|
||||
#define qatomic_rcu_read__nocheck(ptr, valptr) \
|
||||
__atomic_load(ptr, valptr, __ATOMIC_CONSUME);
|
||||
#else
|
||||
#define qatomic_rcu_read__nocheck(ptr, valptr) \
|
||||
__atomic_load(ptr, valptr, __ATOMIC_RELAXED); \
|
||||
smp_read_barrier_depends();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Preprocessor sorcery ahead: use a different identifier for the
|
||||
* local variable in each expansion, so we can nest macro calls
|
||||
* without shadowing variables.
|
||||
*/
|
||||
#define qatomic_rcu_read_internal(ptr, _val) \
|
||||
({ \
|
||||
qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \
|
||||
typeof_strip_qual(*ptr) _val; \
|
||||
qatomic_rcu_read__nocheck(ptr, &_val); \
|
||||
_val; \
|
||||
})
|
||||
#define qatomic_rcu_read(ptr) \
|
||||
qatomic_rcu_read_internal((ptr), MAKE_IDENTIFIER(_val))
|
||||
|
||||
#define qatomic_rcu_set(ptr, i) do { \
|
||||
qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \
|
||||
__atomic_store_n(ptr, i, __ATOMIC_RELEASE); \
|
||||
} while(0)
|
||||
|
||||
#define qatomic_load_acquire(ptr) \
|
||||
({ \
|
||||
qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \
|
||||
typeof_strip_qual(*ptr) _val; \
|
||||
__atomic_load(ptr, &_val, __ATOMIC_ACQUIRE); \
|
||||
_val; \
|
||||
})
|
||||
|
||||
#define qatomic_store_release(ptr, i) do { \
|
||||
qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \
|
||||
__atomic_store_n(ptr, i, __ATOMIC_RELEASE); \
|
||||
} while(0)
|
||||
|
||||
|
||||
/* All the remaining operations are fully sequentially consistent */
|
||||
|
||||
#define qatomic_xchg__nocheck(ptr, i) ({ \
|
||||
__atomic_exchange_n(ptr, (i), __ATOMIC_SEQ_CST); \
|
||||
})
|
||||
|
||||
#define qatomic_xchg(ptr, i) ({ \
|
||||
qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \
|
||||
qatomic_xchg__nocheck(ptr, i); \
|
||||
})
|
||||
|
||||
/* Returns the old value of '*ptr' (whether the cmpxchg failed or not) */
|
||||
#define qatomic_cmpxchg__nocheck(ptr, old, new) ({ \
|
||||
typeof_strip_qual(*ptr) _old = (old); \
|
||||
(void)__atomic_compare_exchange_n(ptr, &_old, new, false, \
|
||||
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); \
|
||||
_old; \
|
||||
})
|
||||
|
||||
#define qatomic_cmpxchg(ptr, old, new) ({ \
|
||||
qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \
|
||||
qatomic_cmpxchg__nocheck(ptr, old, new); \
|
||||
})
|
||||
|
||||
/* Provide shorter names for GCC atomic builtins, return old value */
|
||||
#define qatomic_fetch_inc(ptr) __atomic_fetch_add(ptr, 1, __ATOMIC_SEQ_CST)
|
||||
#define qatomic_fetch_dec(ptr) __atomic_fetch_sub(ptr, 1, __ATOMIC_SEQ_CST)
|
||||
|
||||
#define qatomic_fetch_add(ptr, n) __atomic_fetch_add(ptr, n, __ATOMIC_SEQ_CST)
|
||||
#define qatomic_fetch_sub(ptr, n) __atomic_fetch_sub(ptr, n, __ATOMIC_SEQ_CST)
|
||||
#define qatomic_fetch_and(ptr, n) __atomic_fetch_and(ptr, n, __ATOMIC_SEQ_CST)
|
||||
#define qatomic_fetch_or(ptr, n) __atomic_fetch_or(ptr, n, __ATOMIC_SEQ_CST)
|
||||
#define qatomic_fetch_xor(ptr, n) __atomic_fetch_xor(ptr, n, __ATOMIC_SEQ_CST)
|
||||
|
||||
#define qatomic_inc_fetch(ptr) __atomic_add_fetch(ptr, 1, __ATOMIC_SEQ_CST)
|
||||
#define qatomic_dec_fetch(ptr) __atomic_sub_fetch(ptr, 1, __ATOMIC_SEQ_CST)
|
||||
#define qatomic_add_fetch(ptr, n) __atomic_add_fetch(ptr, n, __ATOMIC_SEQ_CST)
|
||||
#define qatomic_sub_fetch(ptr, n) __atomic_sub_fetch(ptr, n, __ATOMIC_SEQ_CST)
|
||||
#define qatomic_and_fetch(ptr, n) __atomic_and_fetch(ptr, n, __ATOMIC_SEQ_CST)
|
||||
#define qatomic_or_fetch(ptr, n) __atomic_or_fetch(ptr, n, __ATOMIC_SEQ_CST)
|
||||
#define qatomic_xor_fetch(ptr, n) __atomic_xor_fetch(ptr, n, __ATOMIC_SEQ_CST)
|
||||
|
||||
/* And even shorter names that return void. */
|
||||
#define qatomic_inc(ptr) \
|
||||
((void) __atomic_fetch_add(ptr, 1, __ATOMIC_SEQ_CST))
|
||||
#define qatomic_dec(ptr) \
|
||||
((void) __atomic_fetch_sub(ptr, 1, __ATOMIC_SEQ_CST))
|
||||
#define qatomic_add(ptr, n) \
|
||||
((void) __atomic_fetch_add(ptr, n, __ATOMIC_SEQ_CST))
|
||||
#define qatomic_sub(ptr, n) \
|
||||
((void) __atomic_fetch_sub(ptr, n, __ATOMIC_SEQ_CST))
|
||||
#define qatomic_and(ptr, n) \
|
||||
((void) __atomic_fetch_and(ptr, n, __ATOMIC_SEQ_CST))
|
||||
#define qatomic_or(ptr, n) \
|
||||
((void) __atomic_fetch_or(ptr, n, __ATOMIC_SEQ_CST))
|
||||
#define qatomic_xor(ptr, n) \
|
||||
((void) __atomic_fetch_xor(ptr, n, __ATOMIC_SEQ_CST))
|
||||
|
||||
#define smp_wmb() smp_mb_release()
|
||||
#define smp_rmb() smp_mb_acquire()
|
||||
|
||||
/*
|
||||
* SEQ_CST is weaker than the older __sync_* builtins and Linux
|
||||
* kernel read-modify-write atomics. Provide a macro to obtain
|
||||
* the same semantics.
|
||||
*/
|
||||
#if !defined(QEMU_SANITIZE_THREAD) && \
|
||||
(defined(__x86_64__) || defined(__s390x__))
|
||||
# define smp_mb__before_rmw() signal_barrier()
|
||||
# define smp_mb__after_rmw() signal_barrier()
|
||||
#else
|
||||
# define smp_mb__before_rmw() smp_mb()
|
||||
# define smp_mb__after_rmw() smp_mb()
|
||||
#endif
|
||||
|
||||
/*
|
||||
* On some architectures, qatomic_set_mb is more efficient than a store
|
||||
* plus a fence.
|
||||
*/
|
||||
|
||||
#if !defined(QEMU_SANITIZE_THREAD) && \
|
||||
(defined(__x86_64__) || defined(__s390x__))
|
||||
# define qatomic_set_mb(ptr, i) \
|
||||
({ (void)qatomic_xchg(ptr, i); smp_mb__after_rmw(); })
|
||||
#else
|
||||
# define qatomic_set_mb(ptr, i) \
|
||||
({ qatomic_store_release(ptr, i); smp_mb(); })
|
||||
#endif
|
||||
|
||||
#define qatomic_fetch_inc_nonzero(ptr) ({ \
|
||||
typeof_strip_qual(*ptr) _oldn = qatomic_read(ptr); \
|
||||
while (_oldn && qatomic_cmpxchg(ptr, _oldn, _oldn + 1) != _oldn) { \
|
||||
_oldn = qatomic_read(ptr); \
|
||||
} \
|
||||
_oldn; \
|
||||
})
|
||||
|
||||
#endif /* QEMU_ATOMIC_H */
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Simple interface for 128-bit atomic operations.
|
||||
*
|
||||
* Copyright (C) 2018 Linaro, Ltd.
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
* See docs/devel/atomics.rst for discussion about the guarantees each
|
||||
* atomic primitive is meant to provide.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_ATOMIC128_H
|
||||
#define QEMU_ATOMIC128_H
|
||||
|
||||
#include "qemu/atomic.h"
|
||||
#include "qemu/int128.h"
|
||||
|
||||
/*
|
||||
* If __alignof(unsigned __int128) < 16, GCC may refuse to inline atomics
|
||||
* that are supported by the host, e.g. s390x. We can force the pointer to
|
||||
* have our known alignment with __builtin_assume_aligned, however prior to
|
||||
* GCC 13 that was only reliable with optimization enabled. See
|
||||
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107389
|
||||
*/
|
||||
#if defined(CONFIG_ATOMIC128_OPT)
|
||||
# if !defined(__OPTIMIZE__)
|
||||
# define ATTRIBUTE_ATOMIC128_OPT __attribute__((optimize("O1")))
|
||||
# endif
|
||||
# define CONFIG_ATOMIC128
|
||||
#endif
|
||||
#ifndef ATTRIBUTE_ATOMIC128_OPT
|
||||
# define ATTRIBUTE_ATOMIC128_OPT
|
||||
#endif
|
||||
|
||||
/*
|
||||
* GCC is a house divided about supporting large atomic operations.
|
||||
*
|
||||
* For hosts that only have large compare-and-swap, a legalistic reading
|
||||
* of the C++ standard means that one cannot implement __atomic_read on
|
||||
* read-only memory, and thus all atomic operations must synchronize
|
||||
* through libatomic.
|
||||
*
|
||||
* See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80878
|
||||
*
|
||||
* This interpretation is not especially helpful for QEMU.
|
||||
* For system-mode, all RAM is always read/write from the hypervisor.
|
||||
* For user-mode, if the guest doesn't implement such an __atomic_read
|
||||
* then the host need not worry about it either.
|
||||
*
|
||||
* Moreover, using libatomic is not an option, because its interface is
|
||||
* built for std::atomic<T>, and requires that *all* accesses to such an
|
||||
* object go through the library. In our case we do not have an object
|
||||
* in the C/C++ sense, but a view of memory as seen by the guest.
|
||||
* The guest may issue a large atomic operation and then access those
|
||||
* pieces using word-sized accesses. From the hypervisor, we have no
|
||||
* way to connect those two actions.
|
||||
*
|
||||
* Therefore, special case each platform.
|
||||
*/
|
||||
|
||||
#include "host/atomic128-cas.h.inc"
|
||||
#include "host/atomic128-ldst.h.inc"
|
||||
|
||||
#endif /* QEMU_ATOMIC128_H */
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* QEMU Audio subsystem
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#ifndef QEMU_AUDIO_CAPTURE_H
|
||||
#define QEMU_AUDIO_CAPTURE_H
|
||||
|
||||
#include "audio.h"
|
||||
|
||||
struct capture_ops {
|
||||
void (*info) (void *opaque);
|
||||
void (*destroy) (void *opaque);
|
||||
};
|
||||
|
||||
typedef struct CaptureState {
|
||||
void *opaque;
|
||||
struct capture_ops ops;
|
||||
QLIST_ENTRY(CaptureState) entries;
|
||||
} CaptureState;
|
||||
|
||||
CaptureVoiceOut *audio_be_add_capture(
|
||||
AudioBackend *be,
|
||||
const struct audsettings *as,
|
||||
const struct audio_capture_ops *ops,
|
||||
void *opaque);
|
||||
|
||||
void audio_be_del_capture(
|
||||
AudioBackend *be,
|
||||
CaptureVoiceOut *cap,
|
||||
void *cb_opaque);
|
||||
|
||||
#endif /* QEMU_AUDIO_CAPTURE_H */
|
||||
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* QEMU Audio subsystem header
|
||||
*
|
||||
* Copyright (c) 2003-2005 Vassili Karpov (malc)
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_AUDIO_H
|
||||
#define QEMU_AUDIO_H
|
||||
|
||||
#include "qemu/queue.h"
|
||||
#include "qapi/qapi-types-audio.h"
|
||||
#include "hw/core/qdev-properties-system.h"
|
||||
#ifdef CONFIG_GIO
|
||||
#include "gio/gio.h"
|
||||
#endif
|
||||
|
||||
typedef void (*audio_callback_fn) (void *opaque, int avail);
|
||||
|
||||
typedef struct audsettings {
|
||||
int freq;
|
||||
int nchannels;
|
||||
AudioFormat fmt;
|
||||
bool big_endian;
|
||||
} audsettings;
|
||||
|
||||
typedef struct SWVoiceOut SWVoiceOut;
|
||||
typedef struct SWVoiceIn SWVoiceIn;
|
||||
typedef struct CaptureVoiceOut CaptureVoiceOut;
|
||||
|
||||
typedef enum {
|
||||
AUD_CNOTIFY_ENABLE,
|
||||
AUD_CNOTIFY_DISABLE
|
||||
} audcnotification_e;
|
||||
|
||||
struct audio_capture_ops {
|
||||
void (*notify) (void *opaque, audcnotification_e cmd);
|
||||
void (*capture) (void *opaque, const void *buf, int size);
|
||||
void (*destroy) (void *opaque);
|
||||
};
|
||||
|
||||
#define AUDIO_MAX_CHANNELS 16
|
||||
typedef struct Volume {
|
||||
bool mute;
|
||||
int channels;
|
||||
uint8_t vol[AUDIO_MAX_CHANNELS];
|
||||
} Volume;
|
||||
|
||||
typedef struct AudioBackend {
|
||||
Object parent_obj;
|
||||
} AudioBackend;
|
||||
|
||||
typedef struct AudioBackendClass {
|
||||
ObjectClass parent_class;
|
||||
|
||||
bool (*realize)(AudioBackend *be, Audiodev *dev, Error **errp);
|
||||
const char *(*get_id)(AudioBackend *be);
|
||||
SWVoiceOut *(*open_out)(AudioBackend *be,
|
||||
SWVoiceOut *sw,
|
||||
const char *name,
|
||||
void *callback_opaque,
|
||||
audio_callback_fn callback_fn,
|
||||
const struct audsettings *as);
|
||||
SWVoiceIn *(*open_in)(AudioBackend *be,
|
||||
SWVoiceIn *sw,
|
||||
const char *name,
|
||||
void *callback_opaque,
|
||||
audio_callback_fn callback_fn,
|
||||
const struct audsettings *as);
|
||||
void (*close_out)(AudioBackend *be, SWVoiceOut *sw);
|
||||
void (*close_in)(AudioBackend *be, SWVoiceIn *sw);
|
||||
bool (*is_active_out)(AudioBackend *be, SWVoiceOut *sw);
|
||||
bool (*is_active_in)(AudioBackend *be, SWVoiceIn *sw);
|
||||
void (*set_active_out)(AudioBackend *be, SWVoiceOut *sw, bool on);
|
||||
void (*set_active_in)(AudioBackend *be, SWVoiceIn *sw, bool on);
|
||||
void (*set_volume_out)(AudioBackend *be, SWVoiceOut *sw, Volume *vol);
|
||||
void (*set_volume_in)(AudioBackend *be, SWVoiceIn *sw, Volume *vol);
|
||||
size_t (*write)(AudioBackend *be, SWVoiceOut *sw, void *buf, size_t size);
|
||||
size_t (*read)(AudioBackend *be, SWVoiceIn *sw, void *buf, size_t size);
|
||||
int (*get_buffer_size_out)(AudioBackend *be, SWVoiceOut *sw);
|
||||
CaptureVoiceOut *(*add_capture)(AudioBackend *be,
|
||||
const struct audsettings *as,
|
||||
const struct audio_capture_ops *ops,
|
||||
void *cb_opaque);
|
||||
void (*del_capture)(AudioBackend *be, CaptureVoiceOut *cap, void *cb_opaque);
|
||||
|
||||
#ifdef CONFIG_GIO
|
||||
bool (*set_dbus_server)(AudioBackend *be,
|
||||
GDBusObjectManagerServer *manager,
|
||||
bool p2p,
|
||||
Error **errp);
|
||||
#endif
|
||||
} AudioBackendClass;
|
||||
|
||||
bool audio_be_check(AudioBackend **be, Error **errp);
|
||||
|
||||
AudioBackend *audio_be_new(Audiodev *dev, Error **errp);
|
||||
|
||||
SWVoiceOut *audio_be_open_out(
|
||||
AudioBackend *be,
|
||||
SWVoiceOut *sw,
|
||||
const char *name,
|
||||
void *callback_opaque,
|
||||
audio_callback_fn callback_fn,
|
||||
const struct audsettings *settings);
|
||||
|
||||
void audio_be_close_out(AudioBackend *be, SWVoiceOut *sw);
|
||||
size_t audio_be_write(AudioBackend *be, SWVoiceOut *sw, void *pcm_buf, size_t size);
|
||||
int audio_be_get_buffer_size_out(AudioBackend *be, SWVoiceOut *sw);
|
||||
void audio_be_set_active_out(AudioBackend *be, SWVoiceOut *sw, bool on);
|
||||
bool audio_be_is_active_out(AudioBackend *be, SWVoiceOut *sw);
|
||||
|
||||
|
||||
void audio_be_set_volume_out(AudioBackend *be, SWVoiceOut *sw, Volume *vol);
|
||||
void audio_be_set_volume_in(AudioBackend *be, SWVoiceIn *sw, Volume *vol);
|
||||
|
||||
static inline void
|
||||
audio_be_set_volume_out_lr(AudioBackend *be, SWVoiceOut *sw,
|
||||
bool mut, uint8_t lvol, uint8_t rvol) {
|
||||
audio_be_set_volume_out(be, sw, &(Volume) {
|
||||
.mute = mut, .channels = 2, .vol = { lvol, rvol }
|
||||
});
|
||||
}
|
||||
|
||||
static inline void
|
||||
audio_be_set_volume_in_lr(AudioBackend *be, SWVoiceIn *sw,
|
||||
bool mut, uint8_t lvol, uint8_t rvol) {
|
||||
audio_be_set_volume_in(be, sw, &(Volume) {
|
||||
.mute = mut, .channels = 2, .vol = { lvol, rvol }
|
||||
});
|
||||
}
|
||||
|
||||
SWVoiceIn *audio_be_open_in(
|
||||
AudioBackend *be,
|
||||
SWVoiceIn *sw,
|
||||
const char *name,
|
||||
void *callback_opaque,
|
||||
audio_callback_fn callback_fn,
|
||||
const struct audsettings *settings
|
||||
);
|
||||
|
||||
void audio_be_close_in(AudioBackend *be, SWVoiceIn *sw);
|
||||
size_t audio_be_read(AudioBackend *be, SWVoiceIn *sw, void *pcm_buf, size_t size);
|
||||
void audio_be_set_active_in(AudioBackend *be, SWVoiceIn *sw, bool on);
|
||||
bool audio_be_is_active_in(AudioBackend *be, SWVoiceIn *sw);
|
||||
|
||||
void audio_cleanup(void);
|
||||
|
||||
typedef struct st_sample st_sample;
|
||||
|
||||
void audio_add_audiodev(Audiodev *audio);
|
||||
void audio_add_default_audiodev(Audiodev *dev, Error **errp);
|
||||
void audio_parse_option(const char *opt);
|
||||
void audio_create_default_audiodevs(void);
|
||||
void audio_init_audiodevs(void);
|
||||
void audio_help(void);
|
||||
|
||||
AudioBackend *audio_be_by_name(const char *name, Error **errp);
|
||||
AudioBackend *audio_get_default_audio_be(Error **errp);
|
||||
const char *audio_be_get_id(AudioBackend *be);
|
||||
#ifdef CONFIG_GIO
|
||||
bool audio_be_can_set_dbus_server(AudioBackend *be);
|
||||
bool audio_be_set_dbus_server(AudioBackend *be,
|
||||
GDBusObjectManagerServer *server,
|
||||
bool p2p,
|
||||
Error **errp);
|
||||
#endif
|
||||
|
||||
const char *audio_application_name(void);
|
||||
|
||||
static inline int audio_format_bits(AudioFormat fmt)
|
||||
{
|
||||
switch (fmt) {
|
||||
case AUDIO_FORMAT_S8:
|
||||
case AUDIO_FORMAT_U8:
|
||||
return 8;
|
||||
|
||||
case AUDIO_FORMAT_S16:
|
||||
case AUDIO_FORMAT_U16:
|
||||
return 16;
|
||||
|
||||
case AUDIO_FORMAT_F32:
|
||||
case AUDIO_FORMAT_S32:
|
||||
case AUDIO_FORMAT_U32:
|
||||
return 32;
|
||||
|
||||
case AUDIO_FORMAT__MAX:
|
||||
break;
|
||||
}
|
||||
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
static inline bool audio_format_is_float(AudioFormat fmt)
|
||||
{
|
||||
return fmt == AUDIO_FORMAT_F32;
|
||||
}
|
||||
|
||||
static inline bool audio_format_is_signed(AudioFormat fmt)
|
||||
{
|
||||
switch (fmt) {
|
||||
case AUDIO_FORMAT_S8:
|
||||
case AUDIO_FORMAT_S16:
|
||||
case AUDIO_FORMAT_S32:
|
||||
case AUDIO_FORMAT_F32:
|
||||
return true;
|
||||
|
||||
case AUDIO_FORMAT_U8:
|
||||
case AUDIO_FORMAT_U16:
|
||||
case AUDIO_FORMAT_U32:
|
||||
return false;
|
||||
|
||||
case AUDIO_FORMAT__MAX:
|
||||
break;
|
||||
}
|
||||
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
#define DEFINE_AUDIO_PROPERTIES(_s, _f) \
|
||||
DEFINE_PROP_AUDIODEV("audiodev", _s, _f)
|
||||
|
||||
#define TYPE_AUDIO_BACKEND "audio-backend"
|
||||
OBJECT_DECLARE_TYPE(AudioBackend, AudioBackendClass, AUDIO_BACKEND)
|
||||
|
||||
#endif /* QEMU_AUDIO_H */
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* QEMU base architecture bit definitions
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef QEMU_BASE_ARCH_DEFS_H
|
||||
#define QEMU_BASE_ARCH_DEFS_H
|
||||
|
||||
#include "qapi/qapi-types-machine.h"
|
||||
|
||||
enum {
|
||||
QEMU_ARCH_ALPHA = (1UL << SYS_EMU_TARGET_ALPHA),
|
||||
QEMU_ARCH_ARM = (1UL << SYS_EMU_TARGET_ARM) |
|
||||
(1UL << SYS_EMU_TARGET_AARCH64),
|
||||
QEMU_ARCH_I386 = (1UL << SYS_EMU_TARGET_I386) |
|
||||
(1UL << SYS_EMU_TARGET_X86_64),
|
||||
QEMU_ARCH_M68K = (1UL << SYS_EMU_TARGET_M68K),
|
||||
QEMU_ARCH_MICROBLAZE = (1UL << SYS_EMU_TARGET_MICROBLAZE),
|
||||
QEMU_ARCH_MIPS = (1UL << SYS_EMU_TARGET_MIPS) |
|
||||
(1UL << SYS_EMU_TARGET_MIPSEL) |
|
||||
(1UL << SYS_EMU_TARGET_MIPS64) |
|
||||
(1UL << SYS_EMU_TARGET_MIPS64EL),
|
||||
QEMU_ARCH_PPC = (1UL << SYS_EMU_TARGET_PPC) |
|
||||
(1UL << SYS_EMU_TARGET_PPC64),
|
||||
QEMU_ARCH_S390X = (1UL << SYS_EMU_TARGET_S390X),
|
||||
QEMU_ARCH_SH4 = (1UL << SYS_EMU_TARGET_SH4) |
|
||||
(1UL << SYS_EMU_TARGET_SH4EB),
|
||||
QEMU_ARCH_SPARC = (1UL << SYS_EMU_TARGET_SPARC) |
|
||||
(1UL << SYS_EMU_TARGET_SPARC64),
|
||||
QEMU_ARCH_XTENSA = (1UL << SYS_EMU_TARGET_XTENSA) |
|
||||
(1UL << SYS_EMU_TARGET_XTENSAEB),
|
||||
QEMU_ARCH_OR1K = (1UL << SYS_EMU_TARGET_OR1K),
|
||||
QEMU_ARCH_TRICORE = (1UL << SYS_EMU_TARGET_TRICORE),
|
||||
QEMU_ARCH_HPPA = (1UL << SYS_EMU_TARGET_HPPA),
|
||||
QEMU_ARCH_RISCV = (1UL << SYS_EMU_TARGET_RISCV32) |
|
||||
(1UL << SYS_EMU_TARGET_RISCV64),
|
||||
QEMU_ARCH_RX = (1UL << SYS_EMU_TARGET_RX),
|
||||
QEMU_ARCH_AVR = (1UL << SYS_EMU_TARGET_AVR),
|
||||
QEMU_ARCH_HEXAGON = (1UL << SYS_EMU_TARGET_HEXAGON),
|
||||
QEMU_ARCH_LOONGARCH = (1UL << SYS_EMU_TARGET_LOONGARCH64),
|
||||
QEMU_ARCH_ALL = UINT32_MAX,
|
||||
};
|
||||
|
||||
QEMU_BUILD_BUG_ON(SYS_EMU_TARGET__MAX > 32);
|
||||
|
||||
/**
|
||||
* qemu_arch_available:
|
||||
* @arch_bitmask: bitmask of QEMU_ARCH_* constants
|
||||
*
|
||||
* Return whether the current target architecture is contained in @arch_bitmask
|
||||
*/
|
||||
bool qemu_arch_available(uint32_t arch_bitmask);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* QEMU base64 helpers
|
||||
*
|
||||
* Copyright (c) 2015 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QEMU_BASE64_H
|
||||
#define QEMU_BASE64_H
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* qbase64_decode:
|
||||
* @input: the (possibly) base64 encoded text
|
||||
* @in_len: length of @input or -1 if NUL terminated
|
||||
* @out_len: filled with length of decoded data
|
||||
* @errp: pointer to a NULL-initialized error object
|
||||
*
|
||||
* Attempt to decode the (possibly) base64 encoded
|
||||
* text provided in @input. If the @input text may
|
||||
* contain embedded NUL characters, or may not be
|
||||
* NUL terminated, then @in_len must be set to the
|
||||
* known size of the @input buffer.
|
||||
*
|
||||
* Note that embedded NULs, or lack of a NUL terminator
|
||||
* are considered invalid base64 data and errors
|
||||
* will be reported to this effect.
|
||||
*
|
||||
* If decoding is successful, the decoded data will
|
||||
* be returned and @out_len set to indicate the
|
||||
* number of bytes in the decoded data. The caller
|
||||
* must use g_free() to free the returned data when
|
||||
* it is no longer required.
|
||||
*
|
||||
* Returns: the decoded data or NULL
|
||||
*/
|
||||
uint8_t *qbase64_decode(const char *input,
|
||||
size_t in_len,
|
||||
size_t *out_len,
|
||||
Error **errp);
|
||||
|
||||
|
||||
#endif /* QEMU_BASE64_H */
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef QEMU_BCD_H
|
||||
#define QEMU_BCD_H
|
||||
|
||||
/* Convert a byte between binary and BCD. */
|
||||
static inline uint8_t to_bcd(uint8_t val)
|
||||
{
|
||||
return ((val / 10) << 4) | (val % 10);
|
||||
}
|
||||
|
||||
static inline uint8_t from_bcd(uint8_t val)
|
||||
{
|
||||
return ((val >> 4) * 10) + (val & 0x0f);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* Bitmap Module
|
||||
*
|
||||
* Copyright (C) 2010 Corentin Chary <[email protected]>
|
||||
*
|
||||
* Mostly inspired by (stolen from) linux/bitmap.h and linux/bitops.h
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef BITMAP_H
|
||||
#define BITMAP_H
|
||||
|
||||
|
||||
#include "qemu/bitops.h"
|
||||
|
||||
/*
|
||||
* The available bitmap operations and their rough meaning in the
|
||||
* case that the bitmap is a single unsigned long are thus:
|
||||
*
|
||||
* Note that nbits should be always a compile time evaluable constant.
|
||||
* Otherwise many inlines will generate horrible code.
|
||||
*
|
||||
* bitmap_zero(dst, nbits) *dst = 0UL
|
||||
* bitmap_fill(dst, nbits) *dst = ~0UL
|
||||
* bitmap_copy(dst, src, nbits) *dst = *src
|
||||
* bitmap_and(dst, src1, src2, nbits) *dst = *src1 & *src2
|
||||
* bitmap_or(dst, src1, src2, nbits) *dst = *src1 | *src2
|
||||
* bitmap_xor(dst, src1, src2, nbits) *dst = *src1 ^ *src2
|
||||
* bitmap_andnot(dst, src1, src2, nbits) *dst = *src1 & ~(*src2)
|
||||
* bitmap_complement(dst, src, nbits) *dst = ~(*src)
|
||||
* bitmap_equal(src1, src2, nbits) Are *src1 and *src2 equal?
|
||||
* bitmap_intersects(src1, src2, nbits) Do *src1 and *src2 overlap?
|
||||
* bitmap_empty(src, nbits) Are all bits zero in *src?
|
||||
* bitmap_full(src, nbits) Are all bits set in *src?
|
||||
* bitmap_set(dst, pos, nbits) Set specified bit area
|
||||
* bitmap_set_atomic(dst, pos, nbits) Set specified bit area with atomic ops
|
||||
* bitmap_clear(dst, pos, nbits) Clear specified bit area
|
||||
* bitmap_test_and_clear_atomic(dst, pos, nbits) Test and clear area
|
||||
* bitmap_find_next_zero_area(buf, len, pos, n, mask) Find bit free area
|
||||
* bitmap_to_le(dst, src, nbits) Convert bitmap to little endian
|
||||
* bitmap_from_le(dst, src, nbits) Convert bitmap from little endian
|
||||
* bitmap_copy_with_src_offset(dst, src, offset, nbits)
|
||||
* *dst = *src (with an offset into src)
|
||||
* bitmap_copy_with_dst_offset(dst, src, offset, nbits)
|
||||
* *dst = *src (with an offset into dst)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Also the following operations apply to bitmaps.
|
||||
*
|
||||
* set_bit(bit, addr) *addr |= bit
|
||||
* clear_bit(bit, addr) *addr &= ~bit
|
||||
* change_bit(bit, addr) *addr ^= bit
|
||||
* test_bit(bit, addr) Is bit set in *addr?
|
||||
* test_and_set_bit(bit, addr) Set bit and return old value
|
||||
* test_and_clear_bit(bit, addr) Clear bit and return old value
|
||||
* test_and_change_bit(bit, addr) Change bit and return old value
|
||||
* find_first_zero_bit(addr, nbits) Position first zero bit in *addr
|
||||
* find_first_bit(addr, nbits) Position first set bit in *addr
|
||||
* find_next_zero_bit(addr, nbits, bit) Position next zero bit in *addr >= bit
|
||||
* find_next_bit(addr, nbits, bit) Position next set bit in *addr >= bit
|
||||
*/
|
||||
|
||||
#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
|
||||
#define BITMAP_LAST_WORD_MASK(nbits) (~0UL >> (-(nbits) & (BITS_PER_LONG - 1)))
|
||||
|
||||
#define DECLARE_BITMAP(name,bits) \
|
||||
unsigned long name[BITS_TO_LONGS(bits)]
|
||||
|
||||
/*
|
||||
* This is for use with the bit32 versions of set_bit() etc;
|
||||
* we don't currently support the full range of bitmap operations
|
||||
* on bitmaps backed by an array of uint32_t.
|
||||
*/
|
||||
#define DECLARE_BITMAP32(name, bits) \
|
||||
uint32_t name[BITS_TO_U32S(bits)]
|
||||
|
||||
#define small_nbits(nbits) \
|
||||
((nbits) <= BITS_PER_LONG)
|
||||
|
||||
int slow_bitmap_empty(const unsigned long *bitmap, long bits);
|
||||
int slow_bitmap_full(const unsigned long *bitmap, long bits);
|
||||
int slow_bitmap_equal(const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, long bits);
|
||||
void slow_bitmap_complement(unsigned long *dst, const unsigned long *src,
|
||||
long bits);
|
||||
int slow_bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, long bits);
|
||||
void slow_bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, long bits);
|
||||
void slow_bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, long bits);
|
||||
int slow_bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, long bits);
|
||||
int slow_bitmap_intersects(const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, long bits);
|
||||
long slow_bitmap_count_one(const unsigned long *bitmap, long nbits);
|
||||
|
||||
static inline unsigned long *bitmap_try_new(long nbits)
|
||||
{
|
||||
long nelem = BITS_TO_LONGS(nbits);
|
||||
return g_try_new0(unsigned long, nelem);
|
||||
}
|
||||
|
||||
static inline unsigned long *bitmap_new(long nbits)
|
||||
{
|
||||
long nelem = BITS_TO_LONGS(nbits);
|
||||
return g_new0(unsigned long, nelem);
|
||||
}
|
||||
|
||||
static inline void bitmap_zero(unsigned long *dst, long nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
*dst = 0UL;
|
||||
} else {
|
||||
long len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
|
||||
memset(dst, 0, len);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void bitmap_fill(unsigned long *dst, long nbits)
|
||||
{
|
||||
size_t nlongs = BITS_TO_LONGS(nbits);
|
||||
if (!small_nbits(nbits)) {
|
||||
long len = (nlongs - 1) * sizeof(unsigned long);
|
||||
memset(dst, 0xff, len);
|
||||
}
|
||||
dst[nlongs - 1] = BITMAP_LAST_WORD_MASK(nbits);
|
||||
}
|
||||
|
||||
static inline void bitmap_copy(unsigned long *dst, const unsigned long *src,
|
||||
long nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
*dst = *src;
|
||||
} else {
|
||||
long len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
|
||||
memcpy(dst, src, len);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int bitmap_and(unsigned long *dst, const unsigned long *src1,
|
||||
const unsigned long *src2, long nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
return (*dst = *src1 & *src2) != 0;
|
||||
}
|
||||
return slow_bitmap_and(dst, src1, src2, nbits);
|
||||
}
|
||||
|
||||
static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
|
||||
const unsigned long *src2, long nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
*dst = *src1 | *src2;
|
||||
} else {
|
||||
slow_bitmap_or(dst, src1, src2, nbits);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void bitmap_xor(unsigned long *dst, const unsigned long *src1,
|
||||
const unsigned long *src2, long nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
*dst = *src1 ^ *src2;
|
||||
} else {
|
||||
slow_bitmap_xor(dst, src1, src2, nbits);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int bitmap_andnot(unsigned long *dst, const unsigned long *src1,
|
||||
const unsigned long *src2, long nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
return (*dst = *src1 & ~(*src2)) != 0;
|
||||
}
|
||||
return slow_bitmap_andnot(dst, src1, src2, nbits);
|
||||
}
|
||||
|
||||
static inline void bitmap_complement(unsigned long *dst,
|
||||
const unsigned long *src,
|
||||
long nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
*dst = ~(*src) & BITMAP_LAST_WORD_MASK(nbits);
|
||||
} else {
|
||||
slow_bitmap_complement(dst, src, nbits);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int bitmap_equal(const unsigned long *src1,
|
||||
const unsigned long *src2, long nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
return ! ((*src1 ^ *src2) & BITMAP_LAST_WORD_MASK(nbits));
|
||||
} else {
|
||||
return slow_bitmap_equal(src1, src2, nbits);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int bitmap_empty(const unsigned long *src, long nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
return ! (*src & BITMAP_LAST_WORD_MASK(nbits));
|
||||
} else {
|
||||
return slow_bitmap_empty(src, nbits);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int bitmap_full(const unsigned long *src, long nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
return ! (~(*src) & BITMAP_LAST_WORD_MASK(nbits));
|
||||
} else {
|
||||
return slow_bitmap_full(src, nbits);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int bitmap_intersects(const unsigned long *src1,
|
||||
const unsigned long *src2, long nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
return ((*src1 & *src2) & BITMAP_LAST_WORD_MASK(nbits)) != 0;
|
||||
} else {
|
||||
return slow_bitmap_intersects(src1, src2, nbits);
|
||||
}
|
||||
}
|
||||
|
||||
static inline long bitmap_count_one(const unsigned long *bitmap, long nbits)
|
||||
{
|
||||
if (unlikely(!nbits)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (small_nbits(nbits)) {
|
||||
return ctpopl(*bitmap & BITMAP_LAST_WORD_MASK(nbits));
|
||||
} else {
|
||||
return slow_bitmap_count_one(bitmap, nbits);
|
||||
}
|
||||
}
|
||||
|
||||
static inline long bitmap_count_one_with_offset(const unsigned long *bitmap,
|
||||
long offset, long nbits)
|
||||
{
|
||||
long aligned_offset = QEMU_ALIGN_DOWN(offset, BITS_PER_LONG);
|
||||
long redundant_bits = offset - aligned_offset;
|
||||
long bits_to_count = nbits + redundant_bits;
|
||||
const unsigned long *bitmap_start = bitmap +
|
||||
aligned_offset / BITS_PER_LONG;
|
||||
|
||||
return bitmap_count_one(bitmap_start, bits_to_count) -
|
||||
bitmap_count_one(bitmap_start, redundant_bits);
|
||||
}
|
||||
|
||||
void bitmap_set(unsigned long *map, long i, long len);
|
||||
void bitmap_set_atomic(unsigned long *map, long i, long len);
|
||||
void bitmap_clear(unsigned long *map, long start, long nr);
|
||||
bool bitmap_test_and_clear_atomic(unsigned long *map, long start, long nr);
|
||||
bool bitmap_test_and_clear(unsigned long *map, long start, long nr);
|
||||
void bitmap_copy_and_clear_atomic(unsigned long *dst, unsigned long *src,
|
||||
long nr);
|
||||
unsigned long bitmap_find_next_zero_area(unsigned long *map,
|
||||
unsigned long size,
|
||||
unsigned long start,
|
||||
unsigned long nr,
|
||||
unsigned long align_mask);
|
||||
|
||||
static inline unsigned long *bitmap_zero_extend(unsigned long *old,
|
||||
long old_nbits, long new_nbits)
|
||||
{
|
||||
long new_nelem = BITS_TO_LONGS(new_nbits);
|
||||
unsigned long *ptr = g_renew(unsigned long, old, new_nelem);
|
||||
bitmap_clear(ptr, old_nbits, new_nbits - old_nbits);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void bitmap_to_le(unsigned long *dst, const unsigned long *src,
|
||||
long nbits);
|
||||
void bitmap_from_le(unsigned long *dst, const unsigned long *src,
|
||||
long nbits);
|
||||
|
||||
void bitmap_copy_with_src_offset(unsigned long *dst, const unsigned long *src,
|
||||
unsigned long offset, unsigned long nbits);
|
||||
void bitmap_copy_with_dst_offset(unsigned long *dst, const unsigned long *src,
|
||||
unsigned long shift, unsigned long nbits);
|
||||
|
||||
#endif /* BITMAP_H */
|
||||
@@ -0,0 +1,822 @@
|
||||
/*
|
||||
* Bitops Module
|
||||
*
|
||||
* Copyright (C) 2010 Corentin Chary <[email protected]>
|
||||
*
|
||||
* Mostly inspired by (stolen from) linux/bitmap.h and linux/bitops.h
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef BITOPS_H
|
||||
#define BITOPS_H
|
||||
|
||||
|
||||
#include "host-utils.h"
|
||||
#include "atomic.h"
|
||||
|
||||
#define BITS_PER_BYTE CHAR_BIT
|
||||
#define BITS_PER_LONG (sizeof (unsigned long) * BITS_PER_BYTE)
|
||||
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
|
||||
#define BITS_TO_U32S(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(uint32_t))
|
||||
|
||||
#define BIT(nr) (1UL << (nr))
|
||||
#define BIT_ULL(nr) (1ULL << (nr))
|
||||
|
||||
#define MAKE_64BIT_MASK(shift, length) \
|
||||
(((~0ULL) >> (64 - (length))) << (shift))
|
||||
|
||||
/**
|
||||
* DOC: Functions operating on arrays of bits
|
||||
*
|
||||
* We provide a set of functions which work on arbitrary-length arrays of
|
||||
* bits. These come in several flavours which vary in what the type of the
|
||||
* underlying storage for the bits is:
|
||||
*
|
||||
* - Bits stored in an array of 'unsigned long': set_bit(), clear_bit(), etc
|
||||
* - Bits stored in an array of 'uint32_t': set_bit32(), clear_bit32(), etc
|
||||
*
|
||||
* Because the 'unsigned long' type has a size which varies between
|
||||
* host systems, the versions using 'uint32_t' are often preferable.
|
||||
* This is particularly the case in a device model where there may
|
||||
* be some guest-visible register view of the bit array.
|
||||
*
|
||||
* We do not currently implement uint32_t versions of find_last_bit(),
|
||||
* find_next_bit(), find_next_zero_bit() or find_first_zero_bit(),
|
||||
* because we haven't yet needed them. If you need them you should
|
||||
* implement them similarly to the 'unsigned long' versions.
|
||||
*
|
||||
* You can declare a bitmap to be used with these functions via the
|
||||
* DECLARE_BITMAP and DECLARE_BITMAP32 macros in bitmap.h.
|
||||
*/
|
||||
|
||||
/**
|
||||
* DOC: 'unsigned long' bit array APIs
|
||||
*/
|
||||
|
||||
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
|
||||
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
|
||||
|
||||
/**
|
||||
* set_bit - Set a bit in memory
|
||||
* @nr: the bit to set
|
||||
* @addr: the address to start counting from
|
||||
*/
|
||||
static inline void set_bit(long nr, unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = addr + BIT_WORD(nr);
|
||||
|
||||
*p |= mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* set_bit_atomic - Set a bit in memory atomically
|
||||
* @nr: the bit to set
|
||||
* @addr: the address to start counting from
|
||||
*/
|
||||
static inline void set_bit_atomic(long nr, unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = addr + BIT_WORD(nr);
|
||||
|
||||
qatomic_or(p, mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* clear_bit - Clears a bit in memory
|
||||
* @nr: Bit to clear
|
||||
* @addr: Address to start counting from
|
||||
*/
|
||||
static inline void clear_bit(long nr, unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = addr + BIT_WORD(nr);
|
||||
|
||||
*p &= ~mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* clear_bit_atomic - Clears a bit in memory atomically
|
||||
* @nr: Bit to clear
|
||||
* @addr: Address to start counting from
|
||||
*/
|
||||
static inline void clear_bit_atomic(long nr, unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = addr + BIT_WORD(nr);
|
||||
|
||||
return qatomic_and(p, ~mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* change_bit - Toggle a bit in memory
|
||||
* @nr: Bit to change
|
||||
* @addr: Address to start counting from
|
||||
*/
|
||||
static inline void change_bit(long nr, unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = addr + BIT_WORD(nr);
|
||||
|
||||
*p ^= mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_set_bit - Set a bit and return its old value
|
||||
* @nr: Bit to set
|
||||
* @addr: Address to count from
|
||||
*/
|
||||
static inline int test_and_set_bit(long nr, unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = addr + BIT_WORD(nr);
|
||||
unsigned long old = *p;
|
||||
|
||||
*p = old | mask;
|
||||
return (old & mask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_clear_bit - Clear a bit and return its old value
|
||||
* @nr: Bit to clear
|
||||
* @addr: Address to count from
|
||||
*/
|
||||
static inline int test_and_clear_bit(long nr, unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = addr + BIT_WORD(nr);
|
||||
unsigned long old = *p;
|
||||
|
||||
*p = old & ~mask;
|
||||
return (old & mask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_change_bit - Change a bit and return its old value
|
||||
* @nr: Bit to change
|
||||
* @addr: Address to count from
|
||||
*/
|
||||
static inline int test_and_change_bit(long nr, unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = addr + BIT_WORD(nr);
|
||||
unsigned long old = *p;
|
||||
|
||||
*p = old ^ mask;
|
||||
return (old & mask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* test_bit - Determine whether a bit is set
|
||||
* @nr: bit number to test
|
||||
* @addr: Address to start counting from
|
||||
*/
|
||||
static inline int test_bit(long nr, const unsigned long *addr)
|
||||
{
|
||||
return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
|
||||
}
|
||||
|
||||
/**
|
||||
* find_last_bit - find the last set bit in a memory region
|
||||
* @addr: The address to start the search at
|
||||
* @size: The maximum size to search
|
||||
*
|
||||
* Returns the bit number of the last set bit,
|
||||
* or @size if there is no set bit in the bitmap.
|
||||
*/
|
||||
unsigned long find_last_bit(const unsigned long *addr,
|
||||
unsigned long size);
|
||||
|
||||
/**
|
||||
* find_next_bit - find the next set bit in a memory region
|
||||
* @addr: The address to base the search on
|
||||
* @offset: The bitnumber to start searching at
|
||||
* @size: The bitmap size in bits
|
||||
*
|
||||
* Returns the bit number of the next set bit,
|
||||
* or @size if there are no further set bits in the bitmap.
|
||||
*/
|
||||
unsigned long find_next_bit(const unsigned long *addr,
|
||||
unsigned long size,
|
||||
unsigned long offset);
|
||||
|
||||
/**
|
||||
* find_next_zero_bit - find the next cleared bit in a memory region
|
||||
* @addr: The address to base the search on
|
||||
* @offset: The bitnumber to start searching at
|
||||
* @size: The bitmap size in bits
|
||||
*
|
||||
* Returns the bit number of the next cleared bit,
|
||||
* or @size if there are no further clear bits in the bitmap.
|
||||
*/
|
||||
|
||||
unsigned long find_next_zero_bit(const unsigned long *addr,
|
||||
unsigned long size,
|
||||
unsigned long offset);
|
||||
|
||||
/**
|
||||
* find_first_bit - find the first set bit in a memory region
|
||||
* @addr: The address to start the search at
|
||||
* @size: The maximum size to search
|
||||
*
|
||||
* Returns the bit number of the first set bit,
|
||||
* or @size if there is no set bit in the bitmap.
|
||||
*/
|
||||
static inline unsigned long find_first_bit(const unsigned long *addr,
|
||||
unsigned long size)
|
||||
{
|
||||
unsigned long result, tmp;
|
||||
|
||||
for (result = 0; result < size; result += BITS_PER_LONG) {
|
||||
tmp = *addr++;
|
||||
if (tmp) {
|
||||
result += ctzl(tmp);
|
||||
return result < size ? result : size;
|
||||
}
|
||||
}
|
||||
/* Not found */
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* find_first_zero_bit - find the first cleared bit in a memory region
|
||||
* @addr: The address to start the search at
|
||||
* @size: The maximum size to search
|
||||
*
|
||||
* Returns the bit number of the first cleared bit,
|
||||
* or @size if there is no clear bit in the bitmap.
|
||||
*/
|
||||
static inline unsigned long find_first_zero_bit(const unsigned long *addr,
|
||||
unsigned long size)
|
||||
{
|
||||
return find_next_zero_bit(addr, size, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* DOC: 'uint32_t' bit array APIs
|
||||
*/
|
||||
|
||||
#define BIT32_MASK(nr) (1UL << ((nr) % 32))
|
||||
#define BIT32_WORD(nr) ((nr) / 32)
|
||||
|
||||
/**
|
||||
* set_bit32 - Set a bit in memory
|
||||
* @nr: the bit to set
|
||||
* @addr: the address to start counting from
|
||||
*/
|
||||
static inline void set_bit32(long nr, uint32_t *addr)
|
||||
{
|
||||
uint32_t mask = BIT32_MASK(nr);
|
||||
uint32_t *p = addr + BIT32_WORD(nr);
|
||||
|
||||
*p |= mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* set_bit32_atomic - Set a bit in memory atomically
|
||||
* @nr: the bit to set
|
||||
* @addr: the address to start counting from
|
||||
*/
|
||||
static inline void set_bit32_atomic(long nr, uint32_t *addr)
|
||||
{
|
||||
uint32_t mask = BIT32_MASK(nr);
|
||||
uint32_t *p = addr + BIT32_WORD(nr);
|
||||
|
||||
qatomic_or(p, mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* clear_bit32 - Clears a bit in memory
|
||||
* @nr: Bit to clear
|
||||
* @addr: Address to start counting from
|
||||
*/
|
||||
static inline void clear_bit32(long nr, uint32_t *addr)
|
||||
{
|
||||
uint32_t mask = BIT32_MASK(nr);
|
||||
uint32_t *p = addr + BIT32_WORD(nr);
|
||||
|
||||
*p &= ~mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* clear_bit32_atomic - Clears a bit in memory atomically
|
||||
* @nr: Bit to clear
|
||||
* @addr: Address to start counting from
|
||||
*/
|
||||
static inline void clear_bit32_atomic(long nr, uint32_t *addr)
|
||||
{
|
||||
uint32_t mask = BIT32_MASK(nr);
|
||||
uint32_t *p = addr + BIT32_WORD(nr);
|
||||
|
||||
return qatomic_and(p, ~mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* change_bit32 - Toggle a bit in memory
|
||||
* @nr: Bit to change
|
||||
* @addr: Address to start counting from
|
||||
*/
|
||||
static inline void change_bit32(long nr, uint32_t *addr)
|
||||
{
|
||||
uint32_t mask = BIT32_MASK(nr);
|
||||
uint32_t *p = addr + BIT32_WORD(nr);
|
||||
|
||||
*p ^= mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_set_bit32 - Set a bit and return its old value
|
||||
* @nr: Bit to set
|
||||
* @addr: Address to count from
|
||||
*/
|
||||
static inline int test_and_set_bit32(long nr, uint32_t *addr)
|
||||
{
|
||||
uint32_t mask = BIT32_MASK(nr);
|
||||
uint32_t *p = addr + BIT32_WORD(nr);
|
||||
uint32_t old = *p;
|
||||
|
||||
*p = old | mask;
|
||||
return (old & mask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_clear_bit32 - Clear a bit and return its old value
|
||||
* @nr: Bit to clear
|
||||
* @addr: Address to count from
|
||||
*/
|
||||
static inline int test_and_clear_bit32(long nr, uint32_t *addr)
|
||||
{
|
||||
uint32_t mask = BIT32_MASK(nr);
|
||||
uint32_t *p = addr + BIT32_WORD(nr);
|
||||
uint32_t old = *p;
|
||||
|
||||
*p = old & ~mask;
|
||||
return (old & mask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_change_bit32 - Change a bit and return its old value
|
||||
* @nr: Bit to change
|
||||
* @addr: Address to count from
|
||||
*/
|
||||
static inline int test_and_change_bit32(long nr, uint32_t *addr)
|
||||
{
|
||||
uint32_t mask = BIT32_MASK(nr);
|
||||
uint32_t *p = addr + BIT32_WORD(nr);
|
||||
uint32_t old = *p;
|
||||
|
||||
*p = old ^ mask;
|
||||
return (old & mask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* test_bit32 - Determine whether a bit is set
|
||||
* @nr: bit number to test
|
||||
* @addr: Address to start counting from
|
||||
*/
|
||||
static inline int test_bit32(long nr, const uint32_t *addr)
|
||||
{
|
||||
return 1U & (addr[BIT32_WORD(nr)] >> (nr & 31));
|
||||
}
|
||||
|
||||
/**
|
||||
* find_first_bit32 - find the first set bit in a memory region
|
||||
* @addr: The address to start the search at
|
||||
* @size: The maximum size to search
|
||||
*
|
||||
* Returns the bit number of the first set bit,
|
||||
* or @size if there is no set bit in the bitmap.
|
||||
*/
|
||||
static inline uint32_t find_first_bit32(const uint32_t *addr, uint32_t size)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
for (result = 0; result < size; result += 32) {
|
||||
uint32_t tmp = *addr++;
|
||||
if (tmp) {
|
||||
result += ctz32(tmp);
|
||||
return result < size ? result : size;
|
||||
}
|
||||
}
|
||||
/* Not found */
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* DOC: Miscellaneous bit operations on single values
|
||||
*
|
||||
* These functions are a collection of useful operations
|
||||
* (rotations, bit extract, bit deposit, etc) on single
|
||||
* integer values.
|
||||
*/
|
||||
|
||||
/**
|
||||
* rol8 - rotate an 8-bit value left
|
||||
* @word: value to rotate
|
||||
* @shift: bits to roll
|
||||
*/
|
||||
static inline uint8_t rol8(uint8_t word, unsigned int shift)
|
||||
{
|
||||
return (word << (shift & 7)) | (word >> (-shift & 7));
|
||||
}
|
||||
|
||||
/**
|
||||
* ror8 - rotate an 8-bit value right
|
||||
* @word: value to rotate
|
||||
* @shift: bits to roll
|
||||
*/
|
||||
static inline uint8_t ror8(uint8_t word, unsigned int shift)
|
||||
{
|
||||
return (word >> (shift & 7)) | (word << (-shift & 7));
|
||||
}
|
||||
|
||||
/**
|
||||
* rol16 - rotate a 16-bit value left
|
||||
* @word: value to rotate
|
||||
* @shift: bits to roll
|
||||
*/
|
||||
static inline uint16_t rol16(uint16_t word, unsigned int shift)
|
||||
{
|
||||
return (word << (shift & 15)) | (word >> (-shift & 15));
|
||||
}
|
||||
|
||||
/**
|
||||
* ror16 - rotate a 16-bit value right
|
||||
* @word: value to rotate
|
||||
* @shift: bits to roll
|
||||
*/
|
||||
static inline uint16_t ror16(uint16_t word, unsigned int shift)
|
||||
{
|
||||
return (word >> (shift & 15)) | (word << (-shift & 15));
|
||||
}
|
||||
|
||||
/**
|
||||
* rol32 - rotate a 32-bit value left
|
||||
* @word: value to rotate
|
||||
* @shift: bits to roll
|
||||
*/
|
||||
static inline uint32_t rol32(uint32_t word, unsigned int shift)
|
||||
{
|
||||
return (word << (shift & 31)) | (word >> (-shift & 31));
|
||||
}
|
||||
|
||||
/**
|
||||
* ror32 - rotate a 32-bit value right
|
||||
* @word: value to rotate
|
||||
* @shift: bits to roll
|
||||
*/
|
||||
static inline uint32_t ror32(uint32_t word, unsigned int shift)
|
||||
{
|
||||
return (word >> (shift & 31)) | (word << (-shift & 31));
|
||||
}
|
||||
|
||||
/**
|
||||
* rol64 - rotate a 64-bit value left
|
||||
* @word: value to rotate
|
||||
* @shift: bits to roll
|
||||
*/
|
||||
static inline uint64_t rol64(uint64_t word, unsigned int shift)
|
||||
{
|
||||
return (word << (shift & 63)) | (word >> (-shift & 63));
|
||||
}
|
||||
|
||||
/**
|
||||
* ror64 - rotate a 64-bit value right
|
||||
* @word: value to rotate
|
||||
* @shift: bits to roll
|
||||
*/
|
||||
static inline uint64_t ror64(uint64_t word, unsigned int shift)
|
||||
{
|
||||
return (word >> (shift & 63)) | (word << (-shift & 63));
|
||||
}
|
||||
|
||||
/**
|
||||
* hswap32 - swap 16-bit halfwords within a 32-bit value
|
||||
* @h: value to swap
|
||||
*/
|
||||
static inline uint32_t hswap32(uint32_t h)
|
||||
{
|
||||
return rol32(h, 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* hswap64 - swap 16-bit halfwords within a 64-bit value
|
||||
* @h: value to swap
|
||||
*/
|
||||
static inline uint64_t hswap64(uint64_t h)
|
||||
{
|
||||
uint64_t m = 0x0000ffff0000ffffull;
|
||||
h = rol64(h, 32);
|
||||
return ((h & m) << 16) | ((h >> 16) & m);
|
||||
}
|
||||
|
||||
/**
|
||||
* wswap64 - swap 32-bit words within a 64-bit value
|
||||
* @h: value to swap
|
||||
*/
|
||||
static inline uint64_t wswap64(uint64_t h)
|
||||
{
|
||||
return rol64(h, 32);
|
||||
}
|
||||
|
||||
/**
|
||||
* extract32:
|
||||
* @value: the value to extract the bit field from
|
||||
* @start: the lowest bit in the bit field (numbered from 0)
|
||||
* @length: the length of the bit field
|
||||
*
|
||||
* Extract from the 32 bit input @value the bit field specified by the
|
||||
* @start and @length parameters, and return it. The bit field must
|
||||
* lie entirely within the 32 bit word. It is valid to request that
|
||||
* all 32 bits are returned (ie @length 32 and @start 0).
|
||||
*
|
||||
* Returns: the value of the bit field extracted from the input value.
|
||||
*/
|
||||
static inline uint32_t extract32(uint32_t value, int start, int length)
|
||||
{
|
||||
assert(start >= 0 && length > 0 && length <= 32 - start);
|
||||
return (value >> start) & (~0U >> (32 - length));
|
||||
}
|
||||
|
||||
/**
|
||||
* extract8:
|
||||
* @value: the value to extract the bit field from
|
||||
* @start: the lowest bit in the bit field (numbered from 0)
|
||||
* @length: the length of the bit field
|
||||
*
|
||||
* Extract from the 8 bit input @value the bit field specified by the
|
||||
* @start and @length parameters, and return it. The bit field must
|
||||
* lie entirely within the 8 bit word. It is valid to request that
|
||||
* all 8 bits are returned (ie @length 8 and @start 0).
|
||||
*
|
||||
* Returns: the value of the bit field extracted from the input value.
|
||||
*/
|
||||
static inline uint8_t extract8(uint8_t value, int start, int length)
|
||||
{
|
||||
assert(start >= 0 && length > 0 && length <= 8 - start);
|
||||
return extract32(value, start, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* extract16:
|
||||
* @value: the value to extract the bit field from
|
||||
* @start: the lowest bit in the bit field (numbered from 0)
|
||||
* @length: the length of the bit field
|
||||
*
|
||||
* Extract from the 16 bit input @value the bit field specified by the
|
||||
* @start and @length parameters, and return it. The bit field must
|
||||
* lie entirely within the 16 bit word. It is valid to request that
|
||||
* all 16 bits are returned (ie @length 16 and @start 0).
|
||||
*
|
||||
* Returns: the value of the bit field extracted from the input value.
|
||||
*/
|
||||
static inline uint16_t extract16(uint16_t value, int start, int length)
|
||||
{
|
||||
assert(start >= 0 && length > 0 && length <= 16 - start);
|
||||
return extract32(value, start, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* extract64:
|
||||
* @value: the value to extract the bit field from
|
||||
* @start: the lowest bit in the bit field (numbered from 0)
|
||||
* @length: the length of the bit field
|
||||
*
|
||||
* Extract from the 64 bit input @value the bit field specified by the
|
||||
* @start and @length parameters, and return it. The bit field must
|
||||
* lie entirely within the 64 bit word. It is valid to request that
|
||||
* all 64 bits are returned (ie @length 64 and @start 0).
|
||||
*
|
||||
* Returns: the value of the bit field extracted from the input value.
|
||||
*/
|
||||
static inline uint64_t extract64(uint64_t value, int start, int length)
|
||||
{
|
||||
assert(start >= 0 && length > 0 && length <= 64 - start);
|
||||
return (value >> start) & (~0ULL >> (64 - length));
|
||||
}
|
||||
|
||||
/**
|
||||
* sextract32:
|
||||
* @value: the value to extract the bit field from
|
||||
* @start: the lowest bit in the bit field (numbered from 0)
|
||||
* @length: the length of the bit field
|
||||
*
|
||||
* Extract from the 32 bit input @value the bit field specified by the
|
||||
* @start and @length parameters, and return it, sign extended to
|
||||
* an int32_t (ie with the most significant bit of the field propagated
|
||||
* to all the upper bits of the return value). The bit field must lie
|
||||
* entirely within the 32 bit word. It is valid to request that
|
||||
* all 32 bits are returned (ie @length 32 and @start 0).
|
||||
*
|
||||
* Returns: the sign extended value of the bit field extracted from the
|
||||
* input value.
|
||||
*/
|
||||
static inline int32_t sextract32(uint32_t value, int start, int length)
|
||||
{
|
||||
assert(start >= 0 && length > 0 && length <= 32 - start);
|
||||
/* Note that this implementation relies on right shift of signed
|
||||
* integers being an arithmetic shift.
|
||||
*/
|
||||
return ((int32_t)(value << (32 - length - start))) >> (32 - length);
|
||||
}
|
||||
|
||||
/**
|
||||
* sextract64:
|
||||
* @value: the value to extract the bit field from
|
||||
* @start: the lowest bit in the bit field (numbered from 0)
|
||||
* @length: the length of the bit field
|
||||
*
|
||||
* Extract from the 64 bit input @value the bit field specified by the
|
||||
* @start and @length parameters, and return it, sign extended to
|
||||
* an int64_t (ie with the most significant bit of the field propagated
|
||||
* to all the upper bits of the return value). The bit field must lie
|
||||
* entirely within the 64 bit word. It is valid to request that
|
||||
* all 64 bits are returned (ie @length 64 and @start 0).
|
||||
*
|
||||
* Returns: the sign extended value of the bit field extracted from the
|
||||
* input value.
|
||||
*/
|
||||
static inline int64_t sextract64(uint64_t value, int start, int length)
|
||||
{
|
||||
assert(start >= 0 && length > 0 && length <= 64 - start);
|
||||
/* Note that this implementation relies on right shift of signed
|
||||
* integers being an arithmetic shift.
|
||||
*/
|
||||
return ((int64_t)(value << (64 - length - start))) >> (64 - length);
|
||||
}
|
||||
|
||||
/**
|
||||
* deposit32:
|
||||
* @value: initial value to insert bit field into
|
||||
* @start: the lowest bit in the bit field (numbered from 0)
|
||||
* @length: the length of the bit field
|
||||
* @fieldval: the value to insert into the bit field
|
||||
*
|
||||
* Deposit @fieldval into the 32 bit @value at the bit field specified
|
||||
* by the @start and @length parameters, and return the modified
|
||||
* @value. Bits of @value outside the bit field are not modified.
|
||||
* Bits of @fieldval above the least significant @length bits are
|
||||
* ignored. The bit field must lie entirely within the 32 bit word.
|
||||
* It is valid to request that all 32 bits are modified (ie @length
|
||||
* 32 and @start 0).
|
||||
*
|
||||
* Returns: the modified @value.
|
||||
*/
|
||||
static inline uint32_t deposit32(uint32_t value, int start, int length,
|
||||
uint32_t fieldval)
|
||||
{
|
||||
uint32_t mask;
|
||||
assert(start >= 0 && length > 0 && length <= 32 - start);
|
||||
mask = (~0U >> (32 - length)) << start;
|
||||
return (value & ~mask) | ((fieldval << start) & mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* deposit64:
|
||||
* @value: initial value to insert bit field into
|
||||
* @start: the lowest bit in the bit field (numbered from 0)
|
||||
* @length: the length of the bit field
|
||||
* @fieldval: the value to insert into the bit field
|
||||
*
|
||||
* Deposit @fieldval into the 64 bit @value at the bit field specified
|
||||
* by the @start and @length parameters, and return the modified
|
||||
* @value. Bits of @value outside the bit field are not modified.
|
||||
* Bits of @fieldval above the least significant @length bits are
|
||||
* ignored. The bit field must lie entirely within the 64 bit word.
|
||||
* It is valid to request that all 64 bits are modified (ie @length
|
||||
* 64 and @start 0).
|
||||
*
|
||||
* Returns: the modified @value.
|
||||
*/
|
||||
static inline uint64_t deposit64(uint64_t value, int start, int length,
|
||||
uint64_t fieldval)
|
||||
{
|
||||
uint64_t mask;
|
||||
assert(start >= 0 && length > 0 && length <= 64 - start);
|
||||
mask = (~0ULL >> (64 - length)) << start;
|
||||
return (value & ~mask) | ((fieldval << start) & mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* half_shuffle32:
|
||||
* @x: 32-bit value (of which only the bottom 16 bits are of interest)
|
||||
*
|
||||
* Given an input value::
|
||||
*
|
||||
* xxxx xxxx xxxx xxxx ABCD EFGH IJKL MNOP
|
||||
*
|
||||
* return the value where the bottom 16 bits are spread out into
|
||||
* the odd bits in the word, and the even bits are zeroed::
|
||||
*
|
||||
* 0A0B 0C0D 0E0F 0G0H 0I0J 0K0L 0M0N 0O0P
|
||||
*
|
||||
* Any bits set in the top half of the input are ignored.
|
||||
*
|
||||
* Returns: the shuffled bits.
|
||||
*/
|
||||
static inline uint32_t half_shuffle32(uint32_t x)
|
||||
{
|
||||
/* This algorithm is from _Hacker's Delight_ section 7-2 "Shuffling Bits".
|
||||
* It ignores any bits set in the top half of the input.
|
||||
*/
|
||||
x = ((x & 0xFF00) << 8) | (x & 0x00FF);
|
||||
x = ((x << 4) | x) & 0x0F0F0F0F;
|
||||
x = ((x << 2) | x) & 0x33333333;
|
||||
x = ((x << 1) | x) & 0x55555555;
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* half_shuffle64:
|
||||
* @x: 64-bit value (of which only the bottom 32 bits are of interest)
|
||||
*
|
||||
* Given an input value::
|
||||
*
|
||||
* xxxx xxxx xxxx .... xxxx xxxx ABCD EFGH IJKL MNOP QRST UVWX YZab cdef
|
||||
*
|
||||
* return the value where the bottom 32 bits are spread out into
|
||||
* the odd bits in the word, and the even bits are zeroed::
|
||||
*
|
||||
* 0A0B 0C0D 0E0F 0G0H 0I0J 0K0L 0M0N .... 0U0V 0W0X 0Y0Z 0a0b 0c0d 0e0f
|
||||
*
|
||||
* Any bits set in the top half of the input are ignored.
|
||||
*
|
||||
* Returns: the shuffled bits.
|
||||
*/
|
||||
static inline uint64_t half_shuffle64(uint64_t x)
|
||||
{
|
||||
/* This algorithm is from _Hacker's Delight_ section 7-2 "Shuffling Bits".
|
||||
* It ignores any bits set in the top half of the input.
|
||||
*/
|
||||
x = ((x & 0xFFFF0000ULL) << 16) | (x & 0xFFFF);
|
||||
x = ((x << 8) | x) & 0x00FF00FF00FF00FFULL;
|
||||
x = ((x << 4) | x) & 0x0F0F0F0F0F0F0F0FULL;
|
||||
x = ((x << 2) | x) & 0x3333333333333333ULL;
|
||||
x = ((x << 1) | x) & 0x5555555555555555ULL;
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* half_unshuffle32:
|
||||
* @x: 32-bit value (of which only the odd bits are of interest)
|
||||
*
|
||||
* Given an input value::
|
||||
*
|
||||
* xAxB xCxD xExF xGxH xIxJ xKxL xMxN xOxP
|
||||
*
|
||||
* return the value where all the odd bits are compressed down
|
||||
* into the low half of the word, and the high half is zeroed::
|
||||
*
|
||||
* 0000 0000 0000 0000 ABCD EFGH IJKL MNOP
|
||||
*
|
||||
* Any even bits set in the input are ignored.
|
||||
*
|
||||
* Returns: the unshuffled bits.
|
||||
*/
|
||||
static inline uint32_t half_unshuffle32(uint32_t x)
|
||||
{
|
||||
/* This algorithm is from _Hacker's Delight_ section 7-2 "Shuffling Bits".
|
||||
* where it is called an inverse half shuffle.
|
||||
*/
|
||||
x &= 0x55555555;
|
||||
x = ((x >> 1) | x) & 0x33333333;
|
||||
x = ((x >> 2) | x) & 0x0F0F0F0F;
|
||||
x = ((x >> 4) | x) & 0x00FF00FF;
|
||||
x = ((x >> 8) | x) & 0x0000FFFF;
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* half_unshuffle64:
|
||||
* @x: 64-bit value (of which only the odd bits are of interest)
|
||||
*
|
||||
* Given an input value::
|
||||
*
|
||||
* xAxB xCxD xExF xGxH xIxJ xKxL xMxN .... xUxV xWxX xYxZ xaxb xcxd xexf
|
||||
*
|
||||
* return the value where all the odd bits are compressed down
|
||||
* into the low half of the word, and the high half is zeroed::
|
||||
*
|
||||
* 0000 0000 0000 .... 0000 0000 ABCD EFGH IJKL MNOP QRST UVWX YZab cdef
|
||||
*
|
||||
* Any even bits set in the input are ignored.
|
||||
*
|
||||
* Returns: the unshuffled bits.
|
||||
*/
|
||||
static inline uint64_t half_unshuffle64(uint64_t x)
|
||||
{
|
||||
/* This algorithm is from _Hacker's Delight_ section 7-2 "Shuffling Bits".
|
||||
* where it is called an inverse half shuffle.
|
||||
*/
|
||||
x &= 0x5555555555555555ULL;
|
||||
x = ((x >> 1) | x) & 0x3333333333333333ULL;
|
||||
x = ((x >> 2) | x) & 0x0F0F0F0F0F0F0F0FULL;
|
||||
x = ((x >> 4) | x) & 0x00FF00FF00FF00FFULL;
|
||||
x = ((x >> 8) | x) & 0x0000FFFF0000FFFFULL;
|
||||
x = ((x >> 16) | x) & 0x00000000FFFFFFFFULL;
|
||||
return x;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,569 @@
|
||||
#ifndef BSWAP_H
|
||||
#define BSWAP_H
|
||||
|
||||
#include "qemu/target-info.h"
|
||||
#include "exec/memop.h"
|
||||
|
||||
#undef bswap16
|
||||
#define bswap16(_x) __builtin_bswap16(_x)
|
||||
#undef bswap32
|
||||
#define bswap32(_x) __builtin_bswap32(_x)
|
||||
#undef bswap64
|
||||
#define bswap64(_x) __builtin_bswap64(_x)
|
||||
|
||||
static inline uint32_t bswap24(uint32_t x)
|
||||
{
|
||||
return (((x & 0x000000ffU) << 16) |
|
||||
((x & 0x0000ff00U) << 0) |
|
||||
((x & 0x00ff0000U) >> 16));
|
||||
}
|
||||
|
||||
static inline void bswap16s(uint16_t *s)
|
||||
{
|
||||
*s = __builtin_bswap16(*s);
|
||||
}
|
||||
|
||||
static inline void bswap24s(uint32_t *s)
|
||||
{
|
||||
*s = bswap24(*s & 0x00ffffffU);
|
||||
}
|
||||
|
||||
static inline void bswap32s(uint32_t *s)
|
||||
{
|
||||
*s = __builtin_bswap32(*s);
|
||||
}
|
||||
|
||||
static inline void bswap64s(uint64_t *s)
|
||||
{
|
||||
*s = __builtin_bswap64(*s);
|
||||
}
|
||||
|
||||
#if HOST_BIG_ENDIAN
|
||||
#define be_bswap(v, size) (v)
|
||||
#define le_bswap(v, size) glue(__builtin_bswap, size)(v)
|
||||
#define be_bswap24(v) (v)
|
||||
#define le_bswap24(v) bswap24(v)
|
||||
#define be_bswaps(v, size)
|
||||
#define le_bswaps(p, size) \
|
||||
do { *p = glue(__builtin_bswap, size)(*p); } while (0)
|
||||
#else
|
||||
#define le_bswap(v, size) (v)
|
||||
#define be_bswap24(v) bswap24(v)
|
||||
#define le_bswap24(v) (v)
|
||||
#define be_bswap(v, size) glue(__builtin_bswap, size)(v)
|
||||
#define le_bswaps(v, size)
|
||||
#define be_bswaps(p, size) \
|
||||
do { *p = glue(__builtin_bswap, size)(*p); } while (0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Endianness conversion functions between host cpu and specified endianness.
|
||||
* (We list the complete set of prototypes produced by the macros below
|
||||
* to assist people who search the headers to find their definitions.)
|
||||
*
|
||||
* uint16_t le16_to_cpu(uint16_t v);
|
||||
* uint32_t le32_to_cpu(uint32_t v);
|
||||
* uint64_t le64_to_cpu(uint64_t v);
|
||||
* uint16_t be16_to_cpu(uint16_t v);
|
||||
* uint32_t be32_to_cpu(uint32_t v);
|
||||
* uint64_t be64_to_cpu(uint64_t v);
|
||||
*
|
||||
* Convert the value @v from the specified format to the native
|
||||
* endianness of the host CPU by byteswapping if necessary, and
|
||||
* return the converted value.
|
||||
*
|
||||
* uint16_t cpu_to_le16(uint16_t v);
|
||||
* uint32_t cpu_to_le32(uint32_t v);
|
||||
* uint64_t cpu_to_le64(uint64_t v);
|
||||
* uint16_t cpu_to_be16(uint16_t v);
|
||||
* uint32_t cpu_to_be32(uint32_t v);
|
||||
* uint64_t cpu_to_be64(uint64_t v);
|
||||
*
|
||||
* Convert the value @v from the native endianness of the host CPU to
|
||||
* the specified format by byteswapping if necessary, and return
|
||||
* the converted value.
|
||||
*
|
||||
* void le16_to_cpus(uint16_t *v);
|
||||
* void le32_to_cpus(uint32_t *v);
|
||||
* void le64_to_cpus(uint64_t *v);
|
||||
* void be16_to_cpus(uint16_t *v);
|
||||
* void be32_to_cpus(uint32_t *v);
|
||||
* void be64_to_cpus(uint64_t *v);
|
||||
*
|
||||
* Do an in-place conversion of the value pointed to by @v from the
|
||||
* specified format to the native endianness of the host CPU.
|
||||
*
|
||||
* void cpu_to_le16s(uint16_t *v);
|
||||
* void cpu_to_le32s(uint32_t *v);
|
||||
* void cpu_to_le64s(uint64_t *v);
|
||||
* void cpu_to_be16s(uint16_t *v);
|
||||
* void cpu_to_be32s(uint32_t *v);
|
||||
* void cpu_to_be64s(uint64_t *v);
|
||||
*
|
||||
* Do an in-place conversion of the value pointed to by @v from the
|
||||
* native endianness of the host CPU to the specified format.
|
||||
*
|
||||
* Both X_to_cpu() and cpu_to_X() perform the same operation; you
|
||||
* should use whichever one is better documenting of the function your
|
||||
* code is performing.
|
||||
*
|
||||
* Do not use these functions for conversion of values which are in guest
|
||||
* memory, since the data may not be sufficiently aligned for the host CPU's
|
||||
* load and store instructions. Instead you should use the ld*_p() and
|
||||
* st*_p() functions, which perform loads and stores of data of any
|
||||
* required size and endianness and handle possible misalignment.
|
||||
*/
|
||||
|
||||
#define CPU_CONVERT(endian, size, type)\
|
||||
static inline type endian ## size ## _to_cpu(type v)\
|
||||
{\
|
||||
return glue(endian, _bswap)(v, size);\
|
||||
}\
|
||||
\
|
||||
static inline type cpu_to_ ## endian ## size(type v)\
|
||||
{\
|
||||
return glue(endian, _bswap)(v, size);\
|
||||
}\
|
||||
\
|
||||
static inline void endian ## size ## _to_cpus(type *p)\
|
||||
{\
|
||||
glue(endian, _bswaps)(p, size);\
|
||||
}\
|
||||
\
|
||||
static inline void cpu_to_ ## endian ## size ## s(type *p)\
|
||||
{\
|
||||
glue(endian, _bswaps)(p, size);\
|
||||
}
|
||||
|
||||
CPU_CONVERT(be, 16, uint16_t)
|
||||
CPU_CONVERT(be, 32, uint32_t)
|
||||
CPU_CONVERT(be, 64, uint64_t)
|
||||
|
||||
CPU_CONVERT(le, 16, uint16_t)
|
||||
CPU_CONVERT(le, 32, uint32_t)
|
||||
CPU_CONVERT(le, 64, uint64_t)
|
||||
|
||||
#undef CPU_CONVERT
|
||||
|
||||
/*
|
||||
* Same as cpu_to_le{16,32,64}, except that gcc will figure the result is
|
||||
* a compile-time constant if you pass in a constant. So this can be
|
||||
* used to initialize static variables.
|
||||
*/
|
||||
#if HOST_BIG_ENDIAN
|
||||
# define const_le64(_x) \
|
||||
((((_x) & 0x00000000000000ffULL) << 56) | \
|
||||
(((_x) & 0x000000000000ff00ULL) << 40) | \
|
||||
(((_x) & 0x0000000000ff0000ULL) << 24) | \
|
||||
(((_x) & 0x00000000ff000000ULL) << 8) | \
|
||||
(((_x) & 0x000000ff00000000ULL) >> 8) | \
|
||||
(((_x) & 0x0000ff0000000000ULL) >> 24) | \
|
||||
(((_x) & 0x00ff000000000000ULL) >> 40) | \
|
||||
(((_x) & 0xff00000000000000ULL) >> 56))
|
||||
# define const_le32(_x) \
|
||||
((((_x) & 0x000000ffU) << 24) | \
|
||||
(((_x) & 0x0000ff00U) << 8) | \
|
||||
(((_x) & 0x00ff0000U) >> 8) | \
|
||||
(((_x) & 0xff000000U) >> 24))
|
||||
# define const_le16(_x) \
|
||||
((((_x) & 0x00ff) << 8) | \
|
||||
(((_x) & 0xff00) >> 8))
|
||||
#else
|
||||
# define const_le64(_x) (_x)
|
||||
# define const_le32(_x) (_x)
|
||||
# define const_le16(_x) (_x)
|
||||
#endif
|
||||
|
||||
/* unaligned/endian-independent pointer access */
|
||||
|
||||
/*
|
||||
* the generic syntax is:
|
||||
*
|
||||
* load: ld{type}{sign}{size}_{endian}_p(ptr)
|
||||
*
|
||||
* store: st{type}{size}_{endian}_p(ptr, val)
|
||||
*
|
||||
* Note there are small differences with the softmmu access API!
|
||||
*
|
||||
* type is:
|
||||
* (empty): integer access
|
||||
* f : float access
|
||||
*
|
||||
* sign is:
|
||||
* (empty): for 32 or 64 bit sizes (including floats and doubles)
|
||||
* u : unsigned
|
||||
* s : signed
|
||||
*
|
||||
* size is:
|
||||
* b: 8 bits
|
||||
* w: 16 bits
|
||||
* 24: 24 bits
|
||||
* l: 32 bits
|
||||
* q: 64 bits
|
||||
*
|
||||
* endian is:
|
||||
* he : host endian
|
||||
* be : big endian
|
||||
* le : little endian
|
||||
* te : target endian
|
||||
* (except for byte accesses, which have no endian infix).
|
||||
*
|
||||
* In all cases these functions take a host pointer.
|
||||
* For accessors that take a guest address rather than a
|
||||
* host address, see the cpu_{ld,st}_* accessors defined in
|
||||
* cpu_ldst.h.
|
||||
*
|
||||
* For cases where the size to be used is not fixed at compile time,
|
||||
* there are
|
||||
* stn_{endian}_p(ptr, sz, val)
|
||||
* which stores @val to @ptr as an @endian-order number @sz bytes in size
|
||||
* and
|
||||
* ldn_{endian}_p(ptr, sz)
|
||||
* which loads @sz bytes from @ptr as an unsigned @endian-order number
|
||||
* and returns it in a uint64_t.
|
||||
*/
|
||||
|
||||
static inline int ldub_p(const void *ptr)
|
||||
{
|
||||
return *(uint8_t *)ptr;
|
||||
}
|
||||
|
||||
static inline int ldsb_p(const void *ptr)
|
||||
{
|
||||
return *(int8_t *)ptr;
|
||||
}
|
||||
|
||||
static inline void stb_p(void *ptr, uint8_t v)
|
||||
{
|
||||
*(uint8_t *)ptr = v;
|
||||
}
|
||||
|
||||
/*
|
||||
* Any compiler worth its salt will turn these memcpy into native unaligned
|
||||
* operations. Thus we don't need to play games with packed attributes, or
|
||||
* inline byte-by-byte stores.
|
||||
* Some compilation environments (eg some fortify-source implementations)
|
||||
* may intercept memcpy() in a way that defeats the compiler optimization,
|
||||
* though, so we use __builtin_memcpy() to give ourselves the best chance
|
||||
* of good performance.
|
||||
*/
|
||||
|
||||
static inline int lduw_he_p(const void *ptr)
|
||||
{
|
||||
uint16_t r;
|
||||
__builtin_memcpy(&r, ptr, sizeof(r));
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline int ldsw_he_p(const void *ptr)
|
||||
{
|
||||
int16_t r;
|
||||
__builtin_memcpy(&r, ptr, sizeof(r));
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void stw_he_p(void *ptr, uint16_t v)
|
||||
{
|
||||
__builtin_memcpy(ptr, &v, sizeof(v));
|
||||
}
|
||||
|
||||
static inline void st24_he_p(void *ptr, uint32_t v)
|
||||
{
|
||||
__builtin_memcpy(ptr, &v, 3);
|
||||
}
|
||||
|
||||
static inline int ldl_he_p(const void *ptr)
|
||||
{
|
||||
int32_t r;
|
||||
__builtin_memcpy(&r, ptr, sizeof(r));
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void stl_he_p(void *ptr, uint32_t v)
|
||||
{
|
||||
__builtin_memcpy(ptr, &v, sizeof(v));
|
||||
}
|
||||
|
||||
static inline uint64_t ldq_he_p(const void *ptr)
|
||||
{
|
||||
uint64_t r;
|
||||
__builtin_memcpy(&r, ptr, sizeof(r));
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void stq_he_p(void *ptr, uint64_t v)
|
||||
{
|
||||
__builtin_memcpy(ptr, &v, sizeof(v));
|
||||
}
|
||||
|
||||
static inline int lduw_le_p(const void *ptr)
|
||||
{
|
||||
return (uint16_t)le_bswap(lduw_he_p(ptr), 16);
|
||||
}
|
||||
|
||||
static inline int ldsw_le_p(const void *ptr)
|
||||
{
|
||||
return (int16_t)le_bswap(lduw_he_p(ptr), 16);
|
||||
}
|
||||
|
||||
static inline int ldl_le_p(const void *ptr)
|
||||
{
|
||||
return le_bswap(ldl_he_p(ptr), 32);
|
||||
}
|
||||
|
||||
static inline uint64_t ldq_le_p(const void *ptr)
|
||||
{
|
||||
return le_bswap(ldq_he_p(ptr), 64);
|
||||
}
|
||||
|
||||
static inline void stw_le_p(void *ptr, uint16_t v)
|
||||
{
|
||||
stw_he_p(ptr, le_bswap(v, 16));
|
||||
}
|
||||
|
||||
static inline void st24_le_p(void *ptr, uint32_t v)
|
||||
{
|
||||
st24_he_p(ptr, le_bswap24(v));
|
||||
}
|
||||
|
||||
static inline void stl_le_p(void *ptr, uint32_t v)
|
||||
{
|
||||
stl_he_p(ptr, le_bswap(v, 32));
|
||||
}
|
||||
|
||||
static inline void stq_le_p(void *ptr, uint64_t v)
|
||||
{
|
||||
stq_he_p(ptr, le_bswap(v, 64));
|
||||
}
|
||||
|
||||
static inline int lduw_be_p(const void *ptr)
|
||||
{
|
||||
return (uint16_t)be_bswap(lduw_he_p(ptr), 16);
|
||||
}
|
||||
|
||||
static inline int ldsw_be_p(const void *ptr)
|
||||
{
|
||||
return (int16_t)be_bswap(lduw_he_p(ptr), 16);
|
||||
}
|
||||
|
||||
static inline int ldl_be_p(const void *ptr)
|
||||
{
|
||||
return be_bswap(ldl_he_p(ptr), 32);
|
||||
}
|
||||
|
||||
static inline uint64_t ldq_be_p(const void *ptr)
|
||||
{
|
||||
return be_bswap(ldq_he_p(ptr), 64);
|
||||
}
|
||||
|
||||
static inline void stw_be_p(void *ptr, uint16_t v)
|
||||
{
|
||||
stw_he_p(ptr, be_bswap(v, 16));
|
||||
}
|
||||
|
||||
static inline void st24_be_p(void *ptr, uint32_t v)
|
||||
{
|
||||
st24_he_p(ptr, be_bswap24(v));
|
||||
}
|
||||
|
||||
static inline void stl_be_p(void *ptr, uint32_t v)
|
||||
{
|
||||
stl_he_p(ptr, be_bswap(v, 32));
|
||||
}
|
||||
|
||||
static inline void stq_be_p(void *ptr, uint64_t v)
|
||||
{
|
||||
stq_he_p(ptr, be_bswap(v, 64));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ldm_p: Load value from host memory (byteswapping if necessary)
|
||||
*
|
||||
* @ptr: the host pointer to be accessed
|
||||
* @mop: #MemOp mask containing access size and optional byteswapping
|
||||
*
|
||||
* Convert the value stored at @ptr in host memory and byteswap if necessary.
|
||||
*
|
||||
* Returns: the converted value.
|
||||
*/
|
||||
static inline uint64_t ldm_p(const void *ptr, MemOp mop)
|
||||
{
|
||||
switch (mop & (MO_SIZE | MO_BSWAP)) {
|
||||
case MO_8:
|
||||
return ldub_p(ptr);
|
||||
case MO_16 | MO_LE:
|
||||
return lduw_le_p(ptr);
|
||||
case MO_16 | MO_BE:
|
||||
return lduw_be_p(ptr);
|
||||
case MO_32 | MO_LE:
|
||||
return ldl_le_p(ptr);
|
||||
case MO_32 | MO_BE:
|
||||
return ldl_be_p(ptr);
|
||||
case MO_64 | MO_LE:
|
||||
return ldq_le_p(ptr);
|
||||
case MO_64 | MO_BE:
|
||||
return ldq_be_p(ptr);
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* stm_p: Store value to host memory (byteswapping if necessary)
|
||||
*
|
||||
* @ptr: the host pointer to be accessed
|
||||
* @mop: #MemOp mask containing access size and optional byteswapping
|
||||
* @val: the value to store
|
||||
*
|
||||
* Convert the value (byteswap if necessary) and store at @ptr in host memory.
|
||||
*/
|
||||
static inline void stm_p(void *ptr, MemOp mop, uint64_t val)
|
||||
{
|
||||
switch (mop & (MO_SIZE | MO_BSWAP)) {
|
||||
case MO_8:
|
||||
stb_p(ptr, val);
|
||||
break;
|
||||
case MO_16 | MO_LE:
|
||||
stw_le_p(ptr, val);
|
||||
break;
|
||||
case MO_16 | MO_BE:
|
||||
stw_be_p(ptr, val);
|
||||
break;
|
||||
case MO_32 | MO_LE:
|
||||
stl_le_p(ptr, val);
|
||||
break;
|
||||
case MO_32 | MO_BE:
|
||||
stl_be_p(ptr, val);
|
||||
break;
|
||||
case MO_64 | MO_LE:
|
||||
stq_le_p(ptr, val);
|
||||
break;
|
||||
case MO_64 | MO_BE:
|
||||
stq_be_p(ptr, val);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
/* Store v to p as a sz byte value in host order */
|
||||
#define DO_STN_LDN_P(END) \
|
||||
static inline void stn_## END ## _p(void *ptr, int sz, uint64_t v) \
|
||||
{ \
|
||||
switch (sz) { \
|
||||
case 1: \
|
||||
stb_p(ptr, v); \
|
||||
break; \
|
||||
case 2: \
|
||||
stw_ ## END ## _p(ptr, v); \
|
||||
break; \
|
||||
case 4: \
|
||||
stl_ ## END ## _p(ptr, v); \
|
||||
break; \
|
||||
case 8: \
|
||||
stq_ ## END ## _p(ptr, v); \
|
||||
break; \
|
||||
default: \
|
||||
g_assert_not_reached(); \
|
||||
} \
|
||||
} \
|
||||
static inline uint64_t ldn_## END ## _p(const void *ptr, int sz) \
|
||||
{ \
|
||||
switch (sz) { \
|
||||
case 1: \
|
||||
return ldub_p(ptr); \
|
||||
case 2: \
|
||||
return lduw_ ## END ## _p(ptr); \
|
||||
case 4: \
|
||||
return (uint32_t)ldl_ ## END ## _p(ptr); \
|
||||
case 8: \
|
||||
return ldq_ ## END ## _p(ptr); \
|
||||
default: \
|
||||
g_assert_not_reached(); \
|
||||
} \
|
||||
}
|
||||
|
||||
DO_STN_LDN_P(he)
|
||||
DO_STN_LDN_P(le)
|
||||
DO_STN_LDN_P(be)
|
||||
|
||||
#undef DO_STN_LDN_P
|
||||
|
||||
#undef le_bswap
|
||||
#undef be_bswap
|
||||
#undef le_bswaps
|
||||
#undef be_bswaps
|
||||
|
||||
|
||||
/* Return ld{word}_{le,be}_p following target endianness. */
|
||||
#define LOAD_IMPL(word, args...) \
|
||||
do { \
|
||||
if (target_big_endian()) { \
|
||||
return glue(glue(ld, word), _be_p)(args); \
|
||||
} else { \
|
||||
return glue(glue(ld, word), _le_p)(args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static inline int lduw_p(const void *ptr)
|
||||
{
|
||||
LOAD_IMPL(uw, ptr);
|
||||
}
|
||||
|
||||
static inline int ldsw_p(const void *ptr)
|
||||
{
|
||||
LOAD_IMPL(sw, ptr);
|
||||
}
|
||||
|
||||
static inline int ldl_p(const void *ptr)
|
||||
{
|
||||
LOAD_IMPL(l, ptr);
|
||||
}
|
||||
|
||||
static inline uint64_t ldq_p(const void *ptr)
|
||||
{
|
||||
LOAD_IMPL(q, ptr);
|
||||
}
|
||||
|
||||
static inline uint64_t ldn_p(const void *ptr, int sz)
|
||||
{
|
||||
LOAD_IMPL(n, ptr, sz);
|
||||
}
|
||||
|
||||
#undef LOAD_IMPL
|
||||
|
||||
/* Call st{word}_{le,be}_p following target endianness. */
|
||||
#define STORE_IMPL(word, args...) \
|
||||
do { \
|
||||
if (target_big_endian()) { \
|
||||
glue(glue(st, word), _be_p)(args); \
|
||||
} else { \
|
||||
glue(glue(st, word), _le_p)(args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
static inline void stw_p(void *ptr, uint16_t v)
|
||||
{
|
||||
STORE_IMPL(w, ptr, v);
|
||||
}
|
||||
|
||||
static inline void stl_p(void *ptr, uint32_t v)
|
||||
{
|
||||
STORE_IMPL(l, ptr, v);
|
||||
}
|
||||
|
||||
static inline void stq_p(void *ptr, uint64_t v)
|
||||
{
|
||||
STORE_IMPL(q, ptr, v);
|
||||
}
|
||||
|
||||
static inline void stn_p(void *ptr, int sz, uint64_t v)
|
||||
{
|
||||
STORE_IMPL(n, ptr, sz, v);
|
||||
}
|
||||
|
||||
#undef STORE_IMPL
|
||||
|
||||
#endif /* BSWAP_H */
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* QEMU generic buffers
|
||||
*
|
||||
* Copyright (c) 2015 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QEMU_BUFFER_H
|
||||
#define QEMU_BUFFER_H
|
||||
|
||||
|
||||
typedef struct Buffer Buffer;
|
||||
|
||||
/**
|
||||
* Buffer:
|
||||
*
|
||||
* The Buffer object provides a simple dynamically resizing
|
||||
* array, with separate tracking of capacity and usage. This
|
||||
* is typically useful when buffering I/O or processing data.
|
||||
*/
|
||||
|
||||
struct Buffer {
|
||||
char *name;
|
||||
size_t capacity;
|
||||
size_t offset;
|
||||
uint64_t avg_size;
|
||||
uint8_t *buffer;
|
||||
};
|
||||
|
||||
/**
|
||||
* buffer_init:
|
||||
* @buffer: the buffer object
|
||||
* @name: buffer name
|
||||
*
|
||||
* Optionally attach a name to the buffer, to make it easier
|
||||
* to identify in debug traces.
|
||||
*/
|
||||
void buffer_init(Buffer *buffer, const char *name, ...)
|
||||
G_GNUC_PRINTF(2, 3);
|
||||
|
||||
/**
|
||||
* buffer_shrink:
|
||||
* @buffer: the buffer object
|
||||
*
|
||||
* Try to shrink the buffer. Checks current buffer capacity and size
|
||||
* and reduces capacity in case only a fraction of the buffer is
|
||||
* actually used.
|
||||
*/
|
||||
void buffer_shrink(Buffer *buffer);
|
||||
|
||||
/**
|
||||
* buffer_reserve:
|
||||
* @buffer: the buffer object
|
||||
* @len: the minimum required free space
|
||||
*
|
||||
* Ensure that the buffer has space allocated for at least
|
||||
* @len bytes. If the current buffer is too small, it will
|
||||
* be reallocated, possibly to a larger size than requested.
|
||||
*/
|
||||
void buffer_reserve(Buffer *buffer, size_t len);
|
||||
|
||||
/**
|
||||
* buffer_reset:
|
||||
* @buffer: the buffer object
|
||||
*
|
||||
* Reset the length of the stored data to zero, but do
|
||||
* not free / reallocate the memory buffer
|
||||
*/
|
||||
void buffer_reset(Buffer *buffer);
|
||||
|
||||
/**
|
||||
* buffer_free:
|
||||
* @buffer: the buffer object
|
||||
*
|
||||
* Reset the length of the stored data to zero and also
|
||||
* free the internal memory buffer
|
||||
*/
|
||||
void buffer_free(Buffer *buffer);
|
||||
|
||||
/**
|
||||
* buffer_append:
|
||||
* @buffer: the buffer object
|
||||
* @data: the data block to append
|
||||
* @len: the length of @data in bytes
|
||||
*
|
||||
* Append the contents of @data to the end of the buffer.
|
||||
* The caller must ensure that the buffer has sufficient
|
||||
* free space for @len bytes, typically by calling the
|
||||
* buffer_reserve() method prior to appending.
|
||||
*/
|
||||
void buffer_append(Buffer *buffer, const void *data, size_t len);
|
||||
|
||||
/**
|
||||
* buffer_advance:
|
||||
* @buffer: the buffer object
|
||||
* @len: the number of bytes to skip
|
||||
*
|
||||
* Remove @len bytes of data from the head of the buffer.
|
||||
* The internal buffer will not be reallocated, so will
|
||||
* have at least @len bytes of free space after this
|
||||
* call completes
|
||||
*/
|
||||
void buffer_advance(Buffer *buffer, size_t len);
|
||||
|
||||
/**
|
||||
* buffer_end:
|
||||
* @buffer: the buffer object
|
||||
*
|
||||
* Get a pointer to the tail end of the internal buffer
|
||||
* The returned pointer is only valid until the next
|
||||
* call to buffer_reserve().
|
||||
*
|
||||
* Returns: the tail of the buffer
|
||||
*/
|
||||
uint8_t *buffer_end(Buffer *buffer);
|
||||
|
||||
/**
|
||||
* buffer_empty:
|
||||
* @buffer: the buffer object
|
||||
*
|
||||
* Determine if the buffer contains any current data
|
||||
*
|
||||
* Returns: true if the buffer holds data, false otherwise
|
||||
*/
|
||||
gboolean buffer_empty(Buffer *buffer);
|
||||
|
||||
/**
|
||||
* buffer_move_empty:
|
||||
* @to: destination buffer object
|
||||
* @from: source buffer object
|
||||
*
|
||||
* Moves buffer, without copying data. 'to' buffer must be empty.
|
||||
* 'from' buffer is empty and zero-sized on return.
|
||||
*/
|
||||
void buffer_move_empty(Buffer *to, Buffer *from);
|
||||
|
||||
/**
|
||||
* buffer_move:
|
||||
* @to: destination buffer object
|
||||
* @from: source buffer object
|
||||
*
|
||||
* Moves buffer, copying data (unless 'to' buffer happens to be empty).
|
||||
* 'from' buffer is empty and zero-sized on return.
|
||||
*/
|
||||
void buffer_move(Buffer *to, Buffer *from);
|
||||
|
||||
#endif /* QEMU_BUFFER_H */
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Flush the host cpu caches.
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_CACHEFLUSH_H
|
||||
#define QEMU_CACHEFLUSH_H
|
||||
|
||||
/**
|
||||
* flush_idcache_range:
|
||||
* @rx: instruction address
|
||||
* @rw: data address
|
||||
* @len: length to flush
|
||||
*
|
||||
* Flush @len bytes of the data cache at @rw and the icache at @rx
|
||||
* to bring them in sync. The two addresses may be different virtual
|
||||
* mappings of the same physical page(s).
|
||||
*/
|
||||
|
||||
#if defined(__x86_64__) || defined(__s390x__)
|
||||
|
||||
static inline void flush_idcache_range(uintptr_t rx, uintptr_t rw, size_t len)
|
||||
{
|
||||
/* icache is coherent and does not require flushing. */
|
||||
}
|
||||
|
||||
#elif defined(EMSCRIPTEN)
|
||||
|
||||
static inline void flush_idcache_range(uintptr_t rx, uintptr_t rw, size_t len)
|
||||
{
|
||||
/* Wasm doesn't have executable region of memory. */
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void flush_idcache_range(uintptr_t rx, uintptr_t rw, size_t len);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* QEMU_CACHEFLUSH_H */
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* QEMU host cacheinfo information
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
#ifndef QEMU_CACHEINFO_H
|
||||
#define QEMU_CACHEINFO_H
|
||||
|
||||
/*
|
||||
* These variables represent our best guess at the host icache and
|
||||
* dcache sizes, expressed both as the size in bytes and as the
|
||||
* base-2 log of the size in bytes. They are initialized at startup
|
||||
* (via an attribute 'constructor' function).
|
||||
*/
|
||||
extern int qemu_icache_linesize;
|
||||
extern int qemu_icache_linesize_log;
|
||||
extern int qemu_dcache_linesize;
|
||||
extern int qemu_dcache_linesize_log;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* QEMU Chardev Helper
|
||||
*
|
||||
* Copyright (C) 2023 Intel Corporation.
|
||||
*
|
||||
* Authors: Yi Liu <[email protected]>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_CHARDEV_OPEN_H
|
||||
#define QEMU_CHARDEV_OPEN_H
|
||||
|
||||
int open_cdev(const char *devpath, dev_t cdev);
|
||||
#endif
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Helper functionality for distributing a fixed total amount of
|
||||
* an abstract resource among multiple coroutines.
|
||||
*
|
||||
* Copyright (c) 2019 Virtuozzo International GmbH
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_CO_SHARED_RESOURCE_H
|
||||
#define QEMU_CO_SHARED_RESOURCE_H
|
||||
|
||||
/* Accesses to co-shared-resource API are thread-safe */
|
||||
typedef struct SharedResource SharedResource;
|
||||
|
||||
/*
|
||||
* Create SharedResource structure
|
||||
*
|
||||
* @total: total amount of some resource to be shared between clients
|
||||
*/
|
||||
SharedResource *shres_create(uint64_t total);
|
||||
|
||||
/*
|
||||
* Release SharedResource structure
|
||||
*
|
||||
* This function may only be called once everything allocated by all
|
||||
* clients has been deallocated.
|
||||
*/
|
||||
void shres_destroy(SharedResource *s);
|
||||
|
||||
/*
|
||||
* Allocate an amount of @n, and, if necessary, yield until
|
||||
* that becomes possible.
|
||||
*/
|
||||
void coroutine_fn co_get_from_shres(SharedResource *s, uint64_t n);
|
||||
|
||||
/*
|
||||
* Deallocate an amount of @n. The total amount allocated by a caller
|
||||
* does not need to be deallocated/released with a single call, but may
|
||||
* be split over several calls. For example, get(4), get(3), and then
|
||||
* put(5), put(2).
|
||||
*/
|
||||
void coroutine_fn co_put_to_shres(SharedResource *s, uint64_t n);
|
||||
|
||||
|
||||
#endif /* QEMU_CO_SHARED_RESOURCE_H */
|
||||
@@ -0,0 +1,382 @@
|
||||
/* compiler.h: macros to abstract away compiler specifics
|
||||
*
|
||||
* 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 COMPILER_H
|
||||
#define COMPILER_H
|
||||
|
||||
#define HOST_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
|
||||
|
||||
/* HOST_LONG_BITS is the size of a native pointer in bits. */
|
||||
#define HOST_LONG_BITS (__SIZEOF_POINTER__ * 8)
|
||||
|
||||
#if defined __clang_analyzer__ || defined __COVERITY__
|
||||
#define QEMU_STATIC_ANALYSIS 1
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define QEMU_EXTERN_C extern "C"
|
||||
#else
|
||||
#define QEMU_EXTERN_C extern
|
||||
#endif
|
||||
|
||||
#define QEMU_PACKED __attribute__((packed))
|
||||
#define QEMU_ALIGNED(X) __attribute__((aligned(X)))
|
||||
|
||||
#ifndef glue
|
||||
#define xglue(x, y) x ## y
|
||||
#define glue(x, y) xglue(x, y)
|
||||
#define stringify(s) tostring(s)
|
||||
#define tostring(s) #s
|
||||
#endif
|
||||
|
||||
/* Expands into an identifier stemN, where N is another number each time */
|
||||
#define MAKE_IDENTIFIER(stem) glue(stem, __COUNTER__)
|
||||
|
||||
#ifndef likely
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#endif
|
||||
|
||||
#ifndef container_of
|
||||
#define container_of(ptr, type, member) ({ \
|
||||
const typeof(((type *) 0)->member) *__mptr = (ptr); \
|
||||
(type *) ((char *) __mptr - offsetof(type, member));})
|
||||
#endif
|
||||
|
||||
#define sizeof_field(type, field) sizeof(((type *)0)->field)
|
||||
|
||||
/*
|
||||
* Calculate the number of bytes up to and including the given 'field' of
|
||||
* 'container'.
|
||||
*/
|
||||
#define endof(container, field) \
|
||||
(offsetof(container, field) + sizeof_field(container, field))
|
||||
|
||||
/* Convert from a base type to a parent type, with compile time checking. */
|
||||
#define DO_UPCAST(type, field, dev) ( __extension__ ( { \
|
||||
char __attribute__((unused)) offset_must_be_zero[ \
|
||||
-offsetof(type, field)]; \
|
||||
container_of(dev, type, field);}))
|
||||
|
||||
#define typeof_field(type, field) typeof(((type *)0)->field)
|
||||
#define type_check(t1,t2) ((t1*)0 - (t2*)0)
|
||||
|
||||
#define QEMU_BUILD_BUG_ON_STRUCT(x) \
|
||||
struct { \
|
||||
int:(x) ? -1 : 1; \
|
||||
}
|
||||
|
||||
#define QEMU_BUILD_BUG_MSG(x, msg) _Static_assert(!(x), msg)
|
||||
|
||||
#define QEMU_BUILD_BUG_ON(x) QEMU_BUILD_BUG_MSG(x, "not expecting: " #x)
|
||||
|
||||
#define QEMU_BUILD_BUG_ON_ZERO(x) (sizeof(QEMU_BUILD_BUG_ON_STRUCT(x)) - \
|
||||
sizeof(QEMU_BUILD_BUG_ON_STRUCT(x)))
|
||||
|
||||
#if !defined(__clang__) && defined(_WIN32)
|
||||
/*
|
||||
* Map __printf__ to __gnu_printf__ because we want standard format strings even
|
||||
* when MinGW or GLib include files use __printf__.
|
||||
*/
|
||||
# define __printf__ __gnu_printf__
|
||||
#endif
|
||||
|
||||
#ifndef __has_warning
|
||||
#define __has_warning(x) 0 /* compatibility with non-clang compilers */
|
||||
#endif
|
||||
|
||||
#ifndef __has_feature
|
||||
#define __has_feature(x) 0 /* compatibility with non-clang compilers */
|
||||
#endif
|
||||
|
||||
#ifndef __has_builtin
|
||||
#define __has_builtin(x) 0 /* compatibility with non-clang compilers */
|
||||
#endif
|
||||
|
||||
#if __has_builtin(__builtin_assume_aligned) || !defined(__clang__)
|
||||
#define HAS_ASSUME_ALIGNED
|
||||
#endif
|
||||
|
||||
#ifndef __has_attribute
|
||||
#define __has_attribute(x) 0 /* compatibility with older GCC */
|
||||
#endif
|
||||
|
||||
#if defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer)
|
||||
# define QEMU_SANITIZE_ADDRESS 1
|
||||
#endif
|
||||
|
||||
#if defined(__SANITIZE_THREAD__) || __has_feature(thread_sanitizer)
|
||||
# define QEMU_SANITIZE_THREAD 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* GCC doesn't provide __has_attribute() until GCC 5, but we know all the GCC
|
||||
* versions we support have the "flatten" attribute. Clang may not have the
|
||||
* "flatten" attribute but always has __has_attribute() to check for it.
|
||||
*/
|
||||
#if __has_attribute(flatten) || !defined(__clang__)
|
||||
# define QEMU_FLATTEN __attribute__((flatten))
|
||||
#else
|
||||
# define QEMU_FLATTEN
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If __attribute__((error)) is present, use it to produce an error at
|
||||
* compile time. Otherwise, one must wait for the linker to diagnose
|
||||
* the missing symbol.
|
||||
*/
|
||||
#if __has_attribute(error)
|
||||
# define QEMU_ERROR(X) __attribute__((error(X)))
|
||||
#else
|
||||
# define QEMU_ERROR(X)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The nonstring variable attribute specifies that an object or member
|
||||
* declaration with type array of char or pointer to char is intended
|
||||
* to store character arrays that do not necessarily contain a terminating
|
||||
* NUL character. This is useful in detecting uses of such arrays or pointers
|
||||
* with functions that expect NUL-terminated strings, and to avoid warnings
|
||||
* when such an array or pointer is used as an argument to a bounded string
|
||||
* manipulation function such as strncpy.
|
||||
*/
|
||||
#if __has_attribute(nonstring)
|
||||
# define QEMU_NONSTRING __attribute__((nonstring))
|
||||
#else
|
||||
# define QEMU_NONSTRING
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Forced inlining may be desired to encourage constant propagation
|
||||
* of function parameters. However, it can also make debugging harder,
|
||||
* so disable it for a non-optimizing build.
|
||||
*/
|
||||
#if defined(__OPTIMIZE__)
|
||||
#define QEMU_ALWAYS_INLINE __attribute__((always_inline))
|
||||
#else
|
||||
#define QEMU_ALWAYS_INLINE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* In most cases, normal "fallthrough" comments are good enough for
|
||||
* switch-case statements, but sometimes the compiler has problems
|
||||
* with those. In that case you can use QEMU_FALLTHROUGH instead.
|
||||
*/
|
||||
#if __has_attribute(fallthrough)
|
||||
# define QEMU_FALLTHROUGH __attribute__((fallthrough))
|
||||
#else
|
||||
# define QEMU_FALLTHROUGH do {} while (0) /* fallthrough */
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CFI
|
||||
/*
|
||||
* If CFI is enabled, use an attribute to disable cfi-icall on the following
|
||||
* function
|
||||
*/
|
||||
#define QEMU_DISABLE_CFI __attribute__((no_sanitize("cfi-icall")))
|
||||
#else
|
||||
/* If CFI is not enabled, use an empty define to not change the behavior */
|
||||
#define QEMU_DISABLE_CFI
|
||||
#endif
|
||||
|
||||
#if __has_attribute(annotate)
|
||||
#define QEMU_ANNOTATE(x) __attribute__((annotate(x)))
|
||||
#else
|
||||
#define QEMU_ANNOTATE(x)
|
||||
#endif
|
||||
|
||||
#if __has_attribute(used)
|
||||
# define QEMU_USED __attribute__((used))
|
||||
#else
|
||||
# define QEMU_USED
|
||||
#endif
|
||||
|
||||
/*
|
||||
* A priority for __attribute__((constructor(...))) that
|
||||
* will run earlier than the default constructors. Must
|
||||
* only be used for functions that have no dependency
|
||||
* on global initialization of other QEMU subsystems.
|
||||
*/
|
||||
#define QEMU_CONSTRUCTOR_EARLY 101
|
||||
|
||||
/*
|
||||
* Disable -ftrivial-auto-var-init on a local variable.
|
||||
*
|
||||
* Use this in cases where there a method in the device I/O path (or other
|
||||
* important hot paths), that has large variables on the stack. A rule of
|
||||
* thumb is that "large" means a method with 4kb data in the local stack
|
||||
* frame. Any variables which are KB in size, should be annotated with this
|
||||
* attribute, to pre-emptively eliminate any potential overhead from the
|
||||
* compiler's implicit zero'ing of memory.
|
||||
*
|
||||
* Given that this turns off a security hardening feature, when using this
|
||||
* to flag variables, it is important that the code is double-checked to
|
||||
* ensure there is no possible use of uninitialized data in the method.
|
||||
*/
|
||||
#if __has_attribute(uninitialized)
|
||||
# define QEMU_UNINITIALIZED __attribute__((uninitialized))
|
||||
#else
|
||||
# define QEMU_UNINITIALIZED
|
||||
#endif
|
||||
|
||||
/*
|
||||
* http://clang.llvm.org/docs/ThreadSafetyAnalysis.html
|
||||
*
|
||||
* TSA is available since clang 3.6-ish.
|
||||
*/
|
||||
#ifdef __clang__
|
||||
# define TSA(x) __attribute__((x))
|
||||
#else
|
||||
# define TSA(x) /* No TSA, make TSA attributes no-ops. */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* TSA_CAPABILITY() is used to annotate typedefs:
|
||||
*
|
||||
* typedef pthread_mutex_t TSA_CAPABILITY("mutex") tsa_mutex;
|
||||
*/
|
||||
#define TSA_CAPABILITY(x) TSA(capability(x))
|
||||
|
||||
/*
|
||||
* TSA_GUARDED_BY() is used to annotate global variables,
|
||||
* the data is guarded:
|
||||
*
|
||||
* Foo foo TSA_GUARDED_BY(mutex);
|
||||
*/
|
||||
#define TSA_GUARDED_BY(x) TSA(guarded_by(x))
|
||||
|
||||
/*
|
||||
* TSA_PT_GUARDED_BY() is used to annotate global pointers, the data
|
||||
* behind the pointer is guarded.
|
||||
*
|
||||
* Foo* ptr TSA_PT_GUARDED_BY(mutex);
|
||||
*/
|
||||
#define TSA_PT_GUARDED_BY(x) TSA(pt_guarded_by(x))
|
||||
|
||||
/*
|
||||
* The TSA_REQUIRES() is used to annotate functions: the caller of the
|
||||
* function MUST hold the resource, the function will NOT release it.
|
||||
*
|
||||
* More than one mutex may be specified, comma-separated.
|
||||
*
|
||||
* void Foo(void) TSA_REQUIRES(mutex);
|
||||
*/
|
||||
#define TSA_REQUIRES(...) TSA(requires_capability(__VA_ARGS__))
|
||||
#define TSA_REQUIRES_SHARED(...) TSA(requires_shared_capability(__VA_ARGS__))
|
||||
|
||||
/*
|
||||
* TSA_EXCLUDES() is used to annotate functions: the caller of the
|
||||
* function MUST NOT hold resource, the function first acquires the
|
||||
* resource, and then releases it.
|
||||
*
|
||||
* More than one mutex may be specified, comma-separated.
|
||||
*
|
||||
* void Foo(void) TSA_EXCLUDES(mutex);
|
||||
*/
|
||||
#define TSA_EXCLUDES(...) TSA(locks_excluded(__VA_ARGS__))
|
||||
|
||||
/*
|
||||
* TSA_ACQUIRE() is used to annotate functions: the caller of the
|
||||
* function MUST NOT hold the resource, the function will acquire the
|
||||
* resource, but NOT release it.
|
||||
*
|
||||
* More than one mutex may be specified, comma-separated.
|
||||
*
|
||||
* void Foo(void) TSA_ACQUIRE(mutex);
|
||||
*/
|
||||
#define TSA_ACQUIRE(...) TSA(acquire_capability(__VA_ARGS__))
|
||||
#define TSA_ACQUIRE_SHARED(...) TSA(acquire_shared_capability(__VA_ARGS__))
|
||||
|
||||
/*
|
||||
* TSA_RELEASE() is used to annotate functions: the caller of the
|
||||
* function MUST hold the resource, but the function will then release it.
|
||||
*
|
||||
* More than one mutex may be specified, comma-separated.
|
||||
*
|
||||
* void Foo(void) TSA_RELEASE(mutex);
|
||||
*/
|
||||
#define TSA_RELEASE(...) TSA(release_capability(__VA_ARGS__))
|
||||
#define TSA_RELEASE_SHARED(...) TSA(release_shared_capability(__VA_ARGS__))
|
||||
|
||||
/*
|
||||
* TSA_NO_TSA is used to annotate functions. Use only when you need to.
|
||||
*
|
||||
* void Foo(void) TSA_NO_TSA;
|
||||
*/
|
||||
#define TSA_NO_TSA TSA(no_thread_safety_analysis)
|
||||
|
||||
/*
|
||||
* TSA_ASSERT() is used to annotate functions: This function will assert that
|
||||
* the lock is held. When it returns, the caller of the function is assumed to
|
||||
* already hold the resource.
|
||||
*
|
||||
* More than one mutex may be specified, comma-separated.
|
||||
*/
|
||||
#define TSA_ASSERT(...) TSA(assert_capability(__VA_ARGS__))
|
||||
#define TSA_ASSERT_SHARED(...) TSA(assert_shared_capability(__VA_ARGS__))
|
||||
|
||||
/*
|
||||
* Ugly CPP trick that is like "defined FOO", but also works in C
|
||||
* code. Useful to replace #ifdef with "if" statements; assumes
|
||||
* the symbol was defined with Meson's "config.set()", so it is empty
|
||||
* if defined.
|
||||
*/
|
||||
#define IS_ENABLED(x) IS_EMPTY(x)
|
||||
|
||||
#define IS_EMPTY_JUNK_ junk,
|
||||
#define IS_EMPTY(value) IS_EMPTY_(IS_EMPTY_JUNK_##value)
|
||||
|
||||
/* Expands to either SECOND_ARG(junk, 1, 0) or SECOND_ARG(IS_EMPTY_JUNK_CONFIG_FOO 1, 0) */
|
||||
#define SECOND_ARG(first, second, ...) second
|
||||
#define IS_EMPTY_(junk_maybecomma) SECOND_ARG(junk_maybecomma 1, 0)
|
||||
|
||||
#ifndef __cplusplus
|
||||
/*
|
||||
* Useful in macros that need to declare temporary variables. For example,
|
||||
* the variable that receives the old value of an atomically-accessed
|
||||
* variable must be non-qualified, because atomic builtins return values
|
||||
* through a pointer-type argument as in __atomic_load(&var, &old, MODEL).
|
||||
*
|
||||
* This macro has to handle types smaller than int manually, because of
|
||||
* implicit promotion. int and larger types, as well as pointers, can be
|
||||
* converted to a non-qualified type just by applying a binary operator.
|
||||
*/
|
||||
#define typeof_strip_qual(expr) \
|
||||
typeof( \
|
||||
__builtin_choose_expr( \
|
||||
__builtin_types_compatible_p(typeof(expr), bool) || \
|
||||
__builtin_types_compatible_p(typeof(expr), const bool) || \
|
||||
__builtin_types_compatible_p(typeof(expr), volatile bool) || \
|
||||
__builtin_types_compatible_p(typeof(expr), const volatile bool), \
|
||||
(bool)1, \
|
||||
__builtin_choose_expr( \
|
||||
__builtin_types_compatible_p(typeof(expr), signed char) || \
|
||||
__builtin_types_compatible_p(typeof(expr), const signed char) || \
|
||||
__builtin_types_compatible_p(typeof(expr), volatile signed char) || \
|
||||
__builtin_types_compatible_p(typeof(expr), const volatile signed char), \
|
||||
(signed char)1, \
|
||||
__builtin_choose_expr( \
|
||||
__builtin_types_compatible_p(typeof(expr), unsigned char) || \
|
||||
__builtin_types_compatible_p(typeof(expr), const unsigned char) || \
|
||||
__builtin_types_compatible_p(typeof(expr), volatile unsigned char) || \
|
||||
__builtin_types_compatible_p(typeof(expr), const volatile unsigned char), \
|
||||
(unsigned char)1, \
|
||||
__builtin_choose_expr( \
|
||||
__builtin_types_compatible_p(typeof(expr), signed short) || \
|
||||
__builtin_types_compatible_p(typeof(expr), const signed short) || \
|
||||
__builtin_types_compatible_p(typeof(expr), volatile signed short) || \
|
||||
__builtin_types_compatible_p(typeof(expr), const volatile signed short), \
|
||||
(signed short)1, \
|
||||
__builtin_choose_expr( \
|
||||
__builtin_types_compatible_p(typeof(expr), unsigned short) || \
|
||||
__builtin_types_compatible_p(typeof(expr), const unsigned short) || \
|
||||
__builtin_types_compatible_p(typeof(expr), volatile unsigned short) || \
|
||||
__builtin_types_compatible_p(typeof(expr), const volatile unsigned short), \
|
||||
(unsigned short)1, \
|
||||
(expr)+0))))))
|
||||
#endif
|
||||
|
||||
#endif /* COMPILER_H */
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef QEMU_CONFIG_FILE_H
|
||||
#define QEMU_CONFIG_FILE_H
|
||||
|
||||
typedef void QEMUConfigCB(const char *group, QDict *qdict, void *opaque, Error **errp);
|
||||
|
||||
void qemu_load_module_for_opts(const char *group);
|
||||
QemuOptsList *qemu_find_opts(const char *group);
|
||||
QemuOptsList *qemu_find_opts_err(const char *group, Error **errp);
|
||||
QemuOpts *qemu_find_opts_singleton(const char *group);
|
||||
|
||||
extern QemuOptsList *vm_config_groups[];
|
||||
extern QemuOptsList *drive_config_groups[];
|
||||
|
||||
void qemu_add_opts(QemuOptsList *list);
|
||||
void qemu_add_drive_opts(QemuOptsList *list);
|
||||
int qemu_global_option(const char *str);
|
||||
|
||||
int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname,
|
||||
Error **errp);
|
||||
|
||||
/* A default callback for qemu_read_config_file(). */
|
||||
void qemu_config_do_parse(const char *group, QDict *qdict, void *opaque, Error **errp);
|
||||
|
||||
int qemu_read_config_file(const char *filename, QEMUConfigCB *f, Error **errp);
|
||||
|
||||
/* Parse QDict options as a replacement for a config file (allowing multiple
|
||||
enumerated (0..(n-1)) configuration "sections") */
|
||||
bool qemu_config_parse_qdict(QDict *options, QemuOptsList **lists,
|
||||
Error **errp);
|
||||
|
||||
#endif /* QEMU_CONFIG_FILE_H */
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* QEMU coroutine implementation
|
||||
*
|
||||
* Copyright IBM, Corp. 2011
|
||||
*
|
||||
* Authors:
|
||||
* Stefan Hajnoczi <[email protected]>
|
||||
* Kevin Wolf <[email protected]>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QEMU_COROUTINE_CORE_H
|
||||
#define QEMU_COROUTINE_CORE_H
|
||||
|
||||
/**
|
||||
* Coroutines are a mechanism for stack switching and can be used for
|
||||
* cooperative userspace threading. These functions provide a simple but
|
||||
* useful flavor of coroutines that is suitable for writing sequential code,
|
||||
* rather than callbacks, for operations that need to give up control while
|
||||
* waiting for events to complete.
|
||||
*
|
||||
* These functions are re-entrant and may be used outside the BQL.
|
||||
*
|
||||
* Functions that execute in coroutine context cannot be called
|
||||
* directly from normal functions. Use @coroutine_fn to mark such
|
||||
* functions. For example:
|
||||
*
|
||||
* static void coroutine_fn foo(void) {
|
||||
* ....
|
||||
* }
|
||||
*
|
||||
* In the future it would be nice to have the compiler or a static
|
||||
* checker catch misuse of such functions. This annotation might make
|
||||
* it possible and in the meantime it serves as documentation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Mark a function that executes in coroutine context
|
||||
*
|
||||
*
|
||||
* Functions that execute in coroutine context cannot be called
|
||||
* directly from normal functions. Use @coroutine_fn to mark such
|
||||
* functions. For example:
|
||||
*
|
||||
* static void coroutine_fn foo(void) {
|
||||
* ....
|
||||
* }
|
||||
*
|
||||
* In the future it would be nice to have the compiler or a static
|
||||
* checker catch misuse of such functions. This annotation might make
|
||||
* it possible and in the meantime it serves as documentation.
|
||||
*/
|
||||
|
||||
typedef struct Coroutine Coroutine;
|
||||
typedef struct CoMutex CoMutex;
|
||||
|
||||
/**
|
||||
* Coroutine entry point
|
||||
*
|
||||
* When the coroutine is entered for the first time, opaque is passed in as an
|
||||
* argument.
|
||||
*
|
||||
* When this function returns, the coroutine is destroyed automatically and
|
||||
* execution continues in the caller who last entered the coroutine.
|
||||
*/
|
||||
typedef void coroutine_fn CoroutineEntry(void *opaque);
|
||||
|
||||
/**
|
||||
* Create a new coroutine
|
||||
*
|
||||
* Use qemu_coroutine_enter() to actually transfer control to the coroutine.
|
||||
* The opaque argument is passed as the argument to the entry point.
|
||||
*/
|
||||
Coroutine *qemu_coroutine_create(CoroutineEntry *entry, void *opaque);
|
||||
|
||||
/**
|
||||
* Transfer control to a coroutine
|
||||
*/
|
||||
void qemu_coroutine_enter(Coroutine *coroutine);
|
||||
|
||||
/**
|
||||
* Transfer control to a coroutine if it's not active (i.e. part of the call
|
||||
* stack of the running coroutine). Otherwise, do nothing.
|
||||
*/
|
||||
void qemu_coroutine_enter_if_inactive(Coroutine *co);
|
||||
|
||||
/**
|
||||
* Transfer control to a coroutine and associate it with ctx
|
||||
*/
|
||||
void qemu_aio_coroutine_enter(AioContext *ctx, Coroutine *co);
|
||||
|
||||
/**
|
||||
* Transfer control back to a coroutine's caller
|
||||
*
|
||||
* This function does not return until the coroutine is re-entered using
|
||||
* qemu_coroutine_enter().
|
||||
*/
|
||||
void coroutine_fn qemu_coroutine_yield(void);
|
||||
|
||||
/**
|
||||
* Get the AioContext of the given coroutine
|
||||
*/
|
||||
AioContext *qemu_coroutine_get_aio_context(Coroutine *co);
|
||||
|
||||
/**
|
||||
* Get the currently executing coroutine
|
||||
*/
|
||||
Coroutine *qemu_coroutine_self(void);
|
||||
|
||||
/**
|
||||
* Return whether or not currently inside a coroutine
|
||||
*
|
||||
* This can be used to write functions that work both when in coroutine context
|
||||
* and when not in coroutine context. Note that such functions cannot use the
|
||||
* coroutine_fn annotation since they work outside coroutine context.
|
||||
*/
|
||||
bool qemu_in_coroutine(void);
|
||||
|
||||
/**
|
||||
* Return true if the coroutine is currently entered
|
||||
*
|
||||
* A coroutine is "entered" if it has not yielded from the current
|
||||
* qemu_coroutine_enter() call used to run it. This does not mean that the
|
||||
* coroutine is currently executing code since it may have transferred control
|
||||
* to another coroutine using qemu_coroutine_enter().
|
||||
*
|
||||
* When several coroutines enter each other there may be no way to know which
|
||||
* ones have already been entered. In such situations this function can be
|
||||
* used to avoid recursively entering coroutines.
|
||||
*/
|
||||
bool qemu_coroutine_entered(Coroutine *co);
|
||||
|
||||
/**
|
||||
* Initialises a CoMutex. This must be called before any other operation is used
|
||||
* on the CoMutex.
|
||||
*/
|
||||
void qemu_co_mutex_init(CoMutex *mutex);
|
||||
|
||||
/**
|
||||
* Locks the mutex. If the lock cannot be taken immediately, control is
|
||||
* transferred to the caller of the current coroutine.
|
||||
*/
|
||||
void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex);
|
||||
|
||||
/**
|
||||
* Unlocks the mutex and schedules the next coroutine that was waiting for this
|
||||
* lock to be run.
|
||||
*/
|
||||
void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* QEMU Thread Local Storage for coroutines
|
||||
*
|
||||
* Copyright Red Hat
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
* It is forbidden to access Thread Local Storage in coroutines because
|
||||
* compiler optimizations may cause values to be cached across coroutine
|
||||
* re-entry. Coroutines can run in more than one thread through the course of
|
||||
* their life, leading bugs when stale TLS values from the wrong thread are
|
||||
* used as a result of compiler optimization.
|
||||
*
|
||||
* An example is:
|
||||
*
|
||||
* ..code-block:: c
|
||||
* :caption: A coroutine that may see the wrong TLS value
|
||||
*
|
||||
* static __thread AioContext *current_aio_context;
|
||||
* ...
|
||||
* static void coroutine_fn foo(void)
|
||||
* {
|
||||
* aio_notify(current_aio_context);
|
||||
* qemu_coroutine_yield();
|
||||
* aio_notify(current_aio_context); // <-- may be stale after yielding!
|
||||
* }
|
||||
*
|
||||
* This header provides macros for safely defining variables in Thread Local
|
||||
* Storage:
|
||||
*
|
||||
* ..code-block:: c
|
||||
* :caption: A coroutine that safely uses TLS
|
||||
*
|
||||
* QEMU_DEFINE_STATIC_CO_TLS(AioContext *, current_aio_context)
|
||||
* ...
|
||||
* static void coroutine_fn foo(void)
|
||||
* {
|
||||
* aio_notify(get_current_aio_context());
|
||||
* qemu_coroutine_yield();
|
||||
* aio_notify(get_current_aio_context()); // <-- safe
|
||||
* }
|
||||
*/
|
||||
|
||||
#ifndef QEMU_COROUTINE_TLS_H
|
||||
#define QEMU_COROUTINE_TLS_H
|
||||
|
||||
/*
|
||||
* To stop the compiler from caching TLS values we define accessor functions
|
||||
* with __attribute__((noinline)) plus asm volatile("") to prevent
|
||||
* optimizations that override noinline.
|
||||
*
|
||||
* The compiler can still analyze noinline code and make optimizations based on
|
||||
* that knowledge, so an inline asm output operand is used to prevent
|
||||
* optimizations that make assumptions about the address of the TLS variable.
|
||||
*
|
||||
* This is fragile and ultimately needs to be solved by a mechanism that is
|
||||
* guaranteed to work by the compiler (e.g. stackless coroutines), but for now
|
||||
* we use this approach to prevent issues.
|
||||
*/
|
||||
|
||||
/**
|
||||
* QEMU_DECLARE_CO_TLS:
|
||||
* @type: the variable's C type
|
||||
* @var: the variable name
|
||||
*
|
||||
* Declare an extern variable in Thread Local Storage from a header file:
|
||||
*
|
||||
* .. code-block:: c
|
||||
* :caption: Declaring an extern variable in Thread Local Storage
|
||||
*
|
||||
* QEMU_DECLARE_CO_TLS(int, my_count)
|
||||
* ...
|
||||
* int c = get_my_count();
|
||||
* set_my_count(c + 1);
|
||||
* *get_ptr_my_count() = 0;
|
||||
*
|
||||
* This is a coroutine-safe replacement for the __thread keyword and is
|
||||
* equivalent to the following code:
|
||||
*
|
||||
* .. code-block:: c
|
||||
* :caption: Declaring a TLS variable using __thread
|
||||
*
|
||||
* extern __thread int my_count;
|
||||
* ...
|
||||
* int c = my_count;
|
||||
* my_count = c + 1;
|
||||
* *(&my_count) = 0;
|
||||
*/
|
||||
#define QEMU_DECLARE_CO_TLS(type, var) \
|
||||
__attribute__((noinline)) type get_##var(void); \
|
||||
__attribute__((noinline)) void set_##var(type v); \
|
||||
__attribute__((noinline)) type *get_ptr_##var(void);
|
||||
|
||||
/**
|
||||
* QEMU_DEFINE_CO_TLS:
|
||||
* @type: the variable's C type
|
||||
* @var: the variable name
|
||||
*
|
||||
* Define a variable in Thread Local Storage that was previously declared from
|
||||
* a header file with QEMU_DECLARE_CO_TLS():
|
||||
*
|
||||
* .. code-block:: c
|
||||
* :caption: Defining a variable in Thread Local Storage
|
||||
*
|
||||
* QEMU_DEFINE_CO_TLS(int, my_count)
|
||||
*
|
||||
* This is a coroutine-safe replacement for the __thread keyword and is
|
||||
* equivalent to the following code:
|
||||
*
|
||||
* .. code-block:: c
|
||||
* :caption: Defining a TLS variable using __thread
|
||||
*
|
||||
* __thread int my_count;
|
||||
*/
|
||||
#define QEMU_DEFINE_CO_TLS(type, var) \
|
||||
static __thread type co_tls_##var; \
|
||||
type get_##var(void) { asm volatile(""); return co_tls_##var; } \
|
||||
void set_##var(type v) { asm volatile(""); co_tls_##var = v; } \
|
||||
type *get_ptr_##var(void) \
|
||||
{ type *ptr = &co_tls_##var; asm volatile("" : "+rm" (ptr)); return ptr; }
|
||||
|
||||
/**
|
||||
* QEMU_DEFINE_STATIC_CO_TLS:
|
||||
* @type: the variable's C type
|
||||
* @var: the variable name
|
||||
*
|
||||
* Define a static variable in Thread Local Storage:
|
||||
*
|
||||
* .. code-block:: c
|
||||
* :caption: Defining a static variable in Thread Local Storage
|
||||
*
|
||||
* QEMU_DEFINE_STATIC_CO_TLS(int, my_count)
|
||||
* ...
|
||||
* int c = get_my_count();
|
||||
* set_my_count(c + 1);
|
||||
* *get_ptr_my_count() = 0;
|
||||
*
|
||||
* This is a coroutine-safe replacement for the __thread keyword and is
|
||||
* equivalent to the following code:
|
||||
*
|
||||
* .. code-block:: c
|
||||
* :caption: Defining a static TLS variable using __thread
|
||||
*
|
||||
* static __thread int my_count;
|
||||
* ...
|
||||
* int c = my_count;
|
||||
* my_count = c + 1;
|
||||
* *(&my_count) = 0;
|
||||
*/
|
||||
#define QEMU_DEFINE_STATIC_CO_TLS(type, var) \
|
||||
static __thread type co_tls_##var; \
|
||||
static __attribute__((noinline, unused)) \
|
||||
type get_##var(void) \
|
||||
{ asm volatile(""); return co_tls_##var; } \
|
||||
static __attribute__((noinline, unused)) \
|
||||
void set_##var(type v) \
|
||||
{ asm volatile(""); co_tls_##var = v; } \
|
||||
static __attribute__((noinline, unused)) \
|
||||
type *get_ptr_##var(void) \
|
||||
{ type *ptr = &co_tls_##var; asm volatile("" : "+rm" (ptr)); return ptr; }
|
||||
|
||||
#endif /* QEMU_COROUTINE_TLS_H */
|
||||
@@ -0,0 +1,321 @@
|
||||
/*
|
||||
* QEMU coroutine implementation
|
||||
*
|
||||
* Copyright IBM, Corp. 2011
|
||||
*
|
||||
* Authors:
|
||||
* Stefan Hajnoczi <[email protected]>
|
||||
* Kevin Wolf <[email protected]>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QEMU_COROUTINE_H
|
||||
#define QEMU_COROUTINE_H
|
||||
|
||||
#include "qemu/coroutine-core.h"
|
||||
#include "qemu/atomic.h"
|
||||
#include "qemu/queue.h"
|
||||
#include "qemu/timer.h"
|
||||
|
||||
/**
|
||||
* Coroutines are a mechanism for stack switching and can be used for
|
||||
* cooperative userspace threading. These functions provide a simple but
|
||||
* useful flavor of coroutines that is suitable for writing sequential code,
|
||||
* rather than callbacks, for operations that need to give up control while
|
||||
* waiting for events to complete.
|
||||
*
|
||||
* These functions are re-entrant and may be used outside the BQL.
|
||||
*
|
||||
* Functions that execute in coroutine context cannot be called
|
||||
* directly from normal functions. Use @coroutine_fn to mark such
|
||||
* functions. For example:
|
||||
*
|
||||
* static void coroutine_fn foo(void) {
|
||||
* ....
|
||||
* }
|
||||
*
|
||||
* In the future it would be nice to have the compiler or a static
|
||||
* checker catch misuse of such functions. This annotation might make
|
||||
* it possible and in the meantime it serves as documentation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides a mutex that can be used to synchronise coroutines
|
||||
*/
|
||||
struct CoWaitRecord;
|
||||
struct CoMutex {
|
||||
/* Count of pending lockers; 0 for a free mutex, 1 for an
|
||||
* uncontended mutex.
|
||||
*/
|
||||
unsigned locked;
|
||||
|
||||
/* Context that is holding the lock. Useful to avoid spinning
|
||||
* when two coroutines on the same AioContext try to get the lock. :)
|
||||
*/
|
||||
AioContext *ctx;
|
||||
|
||||
/* A queue of waiters. Elements are added atomically in front of
|
||||
* from_push. to_pop is only populated, and popped from, by whoever
|
||||
* is in charge of the next wakeup. This can be an unlocker or,
|
||||
* through the handoff protocol, a locker that is about to go to sleep.
|
||||
*/
|
||||
QSLIST_HEAD(, CoWaitRecord) from_push, to_pop;
|
||||
|
||||
unsigned handoff, sequence;
|
||||
|
||||
Coroutine *holder;
|
||||
};
|
||||
|
||||
/**
|
||||
* Assert that the current coroutine holds @mutex.
|
||||
*/
|
||||
static inline coroutine_fn void qemu_co_mutex_assert_locked(CoMutex *mutex)
|
||||
{
|
||||
/*
|
||||
* mutex->holder doesn't need any synchronisation if the assertion holds
|
||||
* true because the mutex protects it. If it doesn't hold true, we still
|
||||
* don't mind if another thread takes or releases mutex behind our back,
|
||||
* because the condition will be false no matter whether we read NULL or
|
||||
* the pointer for any other coroutine.
|
||||
*/
|
||||
assert(qatomic_read(&mutex->locked) &&
|
||||
mutex->holder == qemu_coroutine_self());
|
||||
}
|
||||
|
||||
#include "qemu/lockable.h"
|
||||
|
||||
/**
|
||||
* CoQueues are a mechanism to queue coroutines in order to continue executing
|
||||
* them later. They are similar to condition variables, but they need help
|
||||
* from an external mutex in order to maintain thread-safety.
|
||||
*/
|
||||
typedef struct CoQueue {
|
||||
QSIMPLEQ_HEAD(, Coroutine) entries;
|
||||
} CoQueue;
|
||||
|
||||
/**
|
||||
* Initialise a CoQueue. This must be called before any other operation is used
|
||||
* on the CoQueue.
|
||||
*/
|
||||
void qemu_co_queue_init(CoQueue *queue);
|
||||
|
||||
typedef enum {
|
||||
/*
|
||||
* Enqueue at front instead of back. Use this to re-queue a request when
|
||||
* its wait condition is not satisfied after being woken up.
|
||||
*/
|
||||
CO_QUEUE_WAIT_FRONT = 0x1,
|
||||
} CoQueueWaitFlags;
|
||||
|
||||
/**
|
||||
* Adds the current coroutine to the CoQueue and transfers control to the
|
||||
* caller of the coroutine. The mutex is unlocked during the wait and
|
||||
* locked again afterwards.
|
||||
*/
|
||||
#define qemu_co_queue_wait(queue, lock) \
|
||||
qemu_co_queue_wait_impl(queue, QEMU_MAKE_LOCKABLE(lock), 0)
|
||||
#define qemu_co_queue_wait_flags(queue, lock, flags) \
|
||||
qemu_co_queue_wait_impl(queue, QEMU_MAKE_LOCKABLE(lock), (flags))
|
||||
void coroutine_fn qemu_co_queue_wait_impl(CoQueue *queue, QemuLockable *lock,
|
||||
CoQueueWaitFlags flags);
|
||||
|
||||
/**
|
||||
* Removes the next coroutine from the CoQueue, and queue it to run after
|
||||
* the currently-running coroutine yields.
|
||||
* Returns true if a coroutine was removed, false if the queue is empty.
|
||||
* Used from coroutine context, use qemu_co_enter_next outside.
|
||||
*/
|
||||
bool coroutine_fn qemu_co_queue_next(CoQueue *queue);
|
||||
|
||||
/**
|
||||
* Empties the CoQueue and queues the coroutine to run after
|
||||
* the currently-running coroutine yields.
|
||||
* Used from coroutine context, use qemu_co_enter_all outside.
|
||||
*/
|
||||
void coroutine_fn qemu_co_queue_restart_all(CoQueue *queue);
|
||||
|
||||
/**
|
||||
* Removes the next coroutine from the CoQueue, and wake it up. Unlike
|
||||
* qemu_co_queue_next, this function releases the lock during aio_co_wake
|
||||
* because it is meant to be used outside coroutine context; in that case, the
|
||||
* coroutine is entered immediately, before qemu_co_enter_next returns.
|
||||
*
|
||||
* If used in coroutine context, qemu_co_enter_next is equivalent to
|
||||
* qemu_co_queue_next.
|
||||
*/
|
||||
#define qemu_co_enter_next(queue, lock) \
|
||||
qemu_co_enter_next_impl(queue, QEMU_MAKE_LOCKABLE(lock))
|
||||
bool qemu_co_enter_next_impl(CoQueue *queue, QemuLockable *lock);
|
||||
|
||||
/**
|
||||
* Empties the CoQueue, waking the waiting coroutine one at a time. Unlike
|
||||
* qemu_co_queue_all, this function releases the lock during aio_co_wake
|
||||
* because it is meant to be used outside coroutine context; in that case, the
|
||||
* coroutine is entered immediately, before qemu_co_enter_all returns.
|
||||
*
|
||||
* If used in coroutine context, qemu_co_enter_all is equivalent to
|
||||
* qemu_co_queue_all.
|
||||
*/
|
||||
#define qemu_co_enter_all(queue, lock) \
|
||||
qemu_co_enter_all_impl(queue, QEMU_MAKE_LOCKABLE(lock))
|
||||
void qemu_co_enter_all_impl(CoQueue *queue, QemuLockable *lock);
|
||||
|
||||
/**
|
||||
* Checks if the CoQueue is empty.
|
||||
*/
|
||||
bool qemu_co_queue_empty(CoQueue *queue);
|
||||
|
||||
|
||||
typedef struct CoRwTicket CoRwTicket;
|
||||
typedef struct CoRwlock {
|
||||
CoMutex mutex;
|
||||
|
||||
/* Number of readers, or -1 if owned for writing. */
|
||||
int owners;
|
||||
|
||||
/* Waiting coroutines. */
|
||||
QSIMPLEQ_HEAD(, CoRwTicket) tickets;
|
||||
} CoRwlock;
|
||||
|
||||
/**
|
||||
* Initialises a CoRwlock. This must be called before any other operation
|
||||
* is used on the CoRwlock
|
||||
*/
|
||||
void qemu_co_rwlock_init(CoRwlock *lock);
|
||||
|
||||
/**
|
||||
* Read locks the CoRwlock. If the lock cannot be taken immediately because
|
||||
* of a parallel writer, control is transferred to the caller of the current
|
||||
* coroutine.
|
||||
*/
|
||||
void coroutine_fn qemu_co_rwlock_rdlock(CoRwlock *lock);
|
||||
|
||||
/**
|
||||
* Write Locks the CoRwlock from a reader. This is a bit more efficient than
|
||||
* @qemu_co_rwlock_unlock followed by a separate @qemu_co_rwlock_wrlock.
|
||||
* Note that if the lock cannot be upgraded immediately, control is transferred
|
||||
* to the caller of the current coroutine; another writer might run while
|
||||
* @qemu_co_rwlock_upgrade blocks.
|
||||
*/
|
||||
void coroutine_fn qemu_co_rwlock_upgrade(CoRwlock *lock);
|
||||
|
||||
/**
|
||||
* Downgrades a write-side critical section to a reader. Downgrading with
|
||||
* @qemu_co_rwlock_downgrade never blocks, unlike @qemu_co_rwlock_unlock
|
||||
* followed by @qemu_co_rwlock_rdlock. This makes it more efficient, but
|
||||
* may also sometimes be necessary for correctness.
|
||||
*/
|
||||
void coroutine_fn qemu_co_rwlock_downgrade(CoRwlock *lock);
|
||||
|
||||
/**
|
||||
* Write Locks the mutex. If the lock cannot be taken immediately because
|
||||
* of a parallel reader, control is transferred to the caller of the current
|
||||
* coroutine.
|
||||
*/
|
||||
void coroutine_fn qemu_co_rwlock_wrlock(CoRwlock *lock);
|
||||
|
||||
/**
|
||||
* Unlocks the read/write lock and schedules the next coroutine that was
|
||||
* waiting for this lock to be run.
|
||||
*/
|
||||
void coroutine_fn qemu_co_rwlock_unlock(CoRwlock *lock);
|
||||
|
||||
typedef struct QemuCoSleep {
|
||||
Coroutine *to_wake;
|
||||
} QemuCoSleep;
|
||||
|
||||
/**
|
||||
* Yield the coroutine for a given duration. Initializes @w so that,
|
||||
* during this yield, it can be passed to qemu_co_sleep_wake() to
|
||||
* terminate the sleep.
|
||||
*/
|
||||
void coroutine_fn qemu_co_sleep_ns_wakeable(QemuCoSleep *w,
|
||||
QEMUClockType type, int64_t ns);
|
||||
|
||||
/**
|
||||
* Yield the coroutine until the next call to qemu_co_sleep_wake.
|
||||
*/
|
||||
void coroutine_fn qemu_co_sleep(QemuCoSleep *w);
|
||||
|
||||
static inline void coroutine_fn qemu_co_sleep_ns(QEMUClockType type, int64_t ns)
|
||||
{
|
||||
QemuCoSleep w = { 0 };
|
||||
qemu_co_sleep_ns_wakeable(&w, type, ns);
|
||||
}
|
||||
|
||||
typedef void CleanupFunc(void *opaque);
|
||||
/**
|
||||
* Run entry in a coroutine and start timer. Wait for entry to finish or for
|
||||
* timer to elapse, what happen first. If entry finished, return 0, if timer
|
||||
* elapsed earlier, return -ETIMEDOUT.
|
||||
*
|
||||
* Be careful, entry execution is not canceled, user should handle it somehow.
|
||||
* If @clean is provided, it's called after coroutine finish if timeout
|
||||
* happened.
|
||||
*/
|
||||
int coroutine_fn qemu_co_timeout(CoroutineEntry *entry, void *opaque,
|
||||
uint64_t timeout_ns, CleanupFunc clean);
|
||||
|
||||
/**
|
||||
* Wake a coroutine sleeping in qemu_co_sleep() or qemu_co_sleep_ns_wakeable().
|
||||
* The timer set up by the latter is deleted on wakeup.
|
||||
*
|
||||
* The wake is sticky: if no sleeper is parked on @w at the time of the call,
|
||||
* the wake is recorded on @w and consumed by the next qemu_co_sleep() on the
|
||||
* same @w, which then returns without yielding. This closes the lost-wakeup
|
||||
* window between two sleeps and is the documented behavior callers should
|
||||
* rely on -- e.g. a cancellation signal raised between iterations of a
|
||||
* sleep/work loop will shorten the next sleep instead of being dropped.
|
||||
*
|
||||
* The state persists until consumed: if no further qemu_co_sleep() is ever
|
||||
* called on @w, the pending wake is harmlessly discarded when @w goes away.
|
||||
* Multiple wakes coalesce -- the next sleep consumes at most one.
|
||||
*/
|
||||
void qemu_co_sleep_wake(QemuCoSleep *w);
|
||||
|
||||
/**
|
||||
* Yield until a file descriptor becomes readable
|
||||
*
|
||||
* Note that this function clobbers the handlers for the file descriptor.
|
||||
*/
|
||||
void coroutine_fn yield_until_fd_readable(int fd);
|
||||
|
||||
/**
|
||||
* Increase coroutine pool size
|
||||
*/
|
||||
void qemu_coroutine_inc_pool_size(unsigned int additional_pool_size);
|
||||
|
||||
/**
|
||||
* Decrease coroutine pool size
|
||||
*/
|
||||
void qemu_coroutine_dec_pool_size(unsigned int additional_pool_size);
|
||||
|
||||
/**
|
||||
* Sends a (part of) iovec down a socket, yielding when the socket is full, or
|
||||
* Receives data into a (part of) iovec from a socket,
|
||||
* yielding when there is no data in the socket.
|
||||
* The same interface as qemu_sendv_recvv(), with added yielding.
|
||||
* XXX should mark these as coroutine_fn
|
||||
*/
|
||||
ssize_t coroutine_fn qemu_co_sendv_recvv(int sockfd, struct iovec *iov,
|
||||
unsigned iov_cnt, size_t offset,
|
||||
size_t bytes, bool do_send);
|
||||
#define qemu_co_recvv(sockfd, iov, iov_cnt, offset, bytes) \
|
||||
qemu_co_sendv_recvv(sockfd, iov, iov_cnt, offset, bytes, false)
|
||||
#define qemu_co_sendv(sockfd, iov, iov_cnt, offset, bytes) \
|
||||
qemu_co_sendv_recvv(sockfd, iov, iov_cnt, offset, bytes, true)
|
||||
|
||||
/**
|
||||
* The same as above, but with just a single buffer
|
||||
*/
|
||||
ssize_t coroutine_fn qemu_co_send_recv(int sockfd, void *buf, size_t bytes,
|
||||
bool do_send);
|
||||
#define qemu_co_recv(sockfd, buf, bytes) \
|
||||
qemu_co_send_recv(sockfd, buf, bytes, false)
|
||||
#define qemu_co_send(sockfd, buf, bytes) \
|
||||
qemu_co_send_recv(sockfd, buf, bytes, true)
|
||||
|
||||
#endif /* QEMU_COROUTINE_H */
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Coroutine internals
|
||||
*
|
||||
* Copyright (c) 2011 Kevin Wolf <[email protected]>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_COROUTINE_INT_H
|
||||
#define QEMU_COROUTINE_INT_H
|
||||
|
||||
#include "qemu/queue.h"
|
||||
#include "qemu/coroutine.h"
|
||||
|
||||
#ifdef CONFIG_SAFESTACK
|
||||
/* Pointer to the unsafe stack, defined by the compiler */
|
||||
extern __thread void *__safestack_unsafe_stack_ptr;
|
||||
#endif
|
||||
|
||||
#define COROUTINE_STACK_SIZE (1 << 20)
|
||||
|
||||
typedef enum {
|
||||
COROUTINE_YIELD = 1,
|
||||
COROUTINE_TERMINATE = 2,
|
||||
COROUTINE_ENTER = 3,
|
||||
} CoroutineAction;
|
||||
|
||||
struct Coroutine {
|
||||
CoroutineEntry *entry;
|
||||
void *entry_arg;
|
||||
Coroutine *caller;
|
||||
|
||||
/* Only used when the coroutine has terminated. */
|
||||
QSLIST_ENTRY(Coroutine) pool_next;
|
||||
|
||||
size_t locks_held;
|
||||
|
||||
/* Only used when the coroutine has yielded. */
|
||||
AioContext *ctx;
|
||||
|
||||
/* Used to catch and abort on illegal co-routine entry.
|
||||
* Will contain the name of the function that had first
|
||||
* scheduled the coroutine. */
|
||||
const char *scheduled;
|
||||
|
||||
QSIMPLEQ_ENTRY(Coroutine) co_queue_next;
|
||||
|
||||
/* Coroutines that should be woken up when we yield or terminate.
|
||||
* Only used when the coroutine is running.
|
||||
*/
|
||||
QSIMPLEQ_HEAD(, Coroutine) co_queue_wakeup;
|
||||
|
||||
QSLIST_ENTRY(Coroutine) co_scheduled_next;
|
||||
};
|
||||
|
||||
Coroutine *qemu_coroutine_new(void);
|
||||
void qemu_coroutine_delete(Coroutine *co);
|
||||
CoroutineAction qemu_coroutine_switch(Coroutine *from, Coroutine *to,
|
||||
CoroutineAction action);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,64 @@
|
||||
#ifndef QEMU_CPU_FLOAT_H
|
||||
#define QEMU_CPU_FLOAT_H
|
||||
|
||||
#include "fpu/softfloat-types.h"
|
||||
|
||||
/* Unions for reinterpreting between floats and integers. */
|
||||
|
||||
typedef union {
|
||||
float32 f;
|
||||
uint32_t l;
|
||||
} CPU_FloatU;
|
||||
|
||||
typedef union {
|
||||
float64 d;
|
||||
#if HOST_BIG_ENDIAN
|
||||
struct {
|
||||
uint32_t upper;
|
||||
uint32_t lower;
|
||||
} l;
|
||||
#else
|
||||
struct {
|
||||
uint32_t lower;
|
||||
uint32_t upper;
|
||||
} l;
|
||||
#endif
|
||||
uint64_t ll;
|
||||
} CPU_DoubleU;
|
||||
|
||||
typedef union {
|
||||
floatx80 d;
|
||||
struct {
|
||||
uint64_t lower;
|
||||
uint16_t upper;
|
||||
} l;
|
||||
} CPU_LDoubleU;
|
||||
|
||||
typedef union {
|
||||
float128 q;
|
||||
#if HOST_BIG_ENDIAN
|
||||
struct {
|
||||
uint32_t upmost;
|
||||
uint32_t upper;
|
||||
uint32_t lower;
|
||||
uint32_t lowest;
|
||||
} l;
|
||||
struct {
|
||||
uint64_t upper;
|
||||
uint64_t lower;
|
||||
} ll;
|
||||
#else
|
||||
struct {
|
||||
uint32_t lowest;
|
||||
uint32_t lower;
|
||||
uint32_t upper;
|
||||
uint32_t upmost;
|
||||
} l;
|
||||
struct {
|
||||
uint64_t lower;
|
||||
uint64_t upper;
|
||||
} ll;
|
||||
#endif
|
||||
} CPU_QuadU;
|
||||
|
||||
#endif /* QEMU_CPU_FLOAT_H */
|
||||
@@ -0,0 +1,105 @@
|
||||
/* cpuid.h: Macros to identify the properties of an x86 host.
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_CPUID_H
|
||||
#define QEMU_CPUID_H
|
||||
|
||||
#ifndef CONFIG_CPUID_H
|
||||
# error "<cpuid.h> is unusable with this compiler"
|
||||
#endif
|
||||
|
||||
#include <cpuid.h>
|
||||
|
||||
/* Cover the uses that we have within qemu. */
|
||||
/* ??? Irritating that we have the same information in target/i386/. */
|
||||
|
||||
/* Leaf 1, %edx */
|
||||
#ifndef bit_CMOV
|
||||
#define bit_CMOV (1 << 15)
|
||||
#endif
|
||||
#ifndef bit_SSE2
|
||||
#define bit_SSE2 (1 << 26)
|
||||
#endif
|
||||
|
||||
/* Leaf 1, %ecx */
|
||||
#ifndef bit_PCLMUL
|
||||
#define bit_PCLMUL (1 << 1)
|
||||
#endif
|
||||
#ifndef bit_SSE4_1
|
||||
#define bit_SSE4_1 (1 << 19)
|
||||
#endif
|
||||
#ifndef bit_MOVBE
|
||||
#define bit_MOVBE (1 << 22)
|
||||
#endif
|
||||
#ifndef bit_OSXSAVE
|
||||
#define bit_OSXSAVE (1 << 27)
|
||||
#endif
|
||||
#ifndef bit_AVX
|
||||
#define bit_AVX (1 << 28)
|
||||
#endif
|
||||
|
||||
/* Leaf 7, %ebx */
|
||||
#ifndef bit_BMI
|
||||
#define bit_BMI (1 << 3)
|
||||
#endif
|
||||
#ifndef bit_AVX2
|
||||
#define bit_AVX2 (1 << 5)
|
||||
#endif
|
||||
#ifndef bit_BMI2
|
||||
#define bit_BMI2 (1 << 8)
|
||||
#endif
|
||||
#ifndef bit_AVX512F
|
||||
#define bit_AVX512F (1 << 16)
|
||||
#endif
|
||||
#ifndef bit_AVX512DQ
|
||||
#define bit_AVX512DQ (1 << 17)
|
||||
#endif
|
||||
#ifndef bit_AVX512BW
|
||||
#define bit_AVX512BW (1 << 30)
|
||||
#endif
|
||||
#ifndef bit_AVX512VL
|
||||
#define bit_AVX512VL (1u << 31)
|
||||
#endif
|
||||
|
||||
/* Leaf 7, %ecx */
|
||||
#ifndef bit_AVX512VBMI2
|
||||
#define bit_AVX512VBMI2 (1 << 6)
|
||||
#endif
|
||||
#ifndef bit_GFNI
|
||||
#define bit_GFNI (1 << 8)
|
||||
#endif
|
||||
|
||||
/* Leaf 0x80000001, %ecx */
|
||||
#ifndef bit_LZCNT
|
||||
#define bit_LZCNT (1 << 5)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Signatures for different CPU implementations as returned from Leaf 0.
|
||||
*/
|
||||
|
||||
#ifndef signature_INTEL_ecx
|
||||
/* "Genu" "ineI" "ntel" */
|
||||
#define signature_INTEL_ebx 0x756e6547
|
||||
#define signature_INTEL_edx 0x49656e69
|
||||
#define signature_INTEL_ecx 0x6c65746e
|
||||
#endif
|
||||
|
||||
#ifndef signature_AMD_ecx
|
||||
/* "Auth" "enti" "cAMD" */
|
||||
#define signature_AMD_ebx 0x68747541
|
||||
#define signature_AMD_edx 0x69746e65
|
||||
#define signature_AMD_ecx 0x444d4163
|
||||
#endif
|
||||
|
||||
static inline unsigned xgetbv_low(unsigned c)
|
||||
{
|
||||
unsigned a, d;
|
||||
asm("xgetbv" : "=a"(a), "=d"(d) : "c"(c));
|
||||
return a;
|
||||
}
|
||||
|
||||
#endif /* QEMU_CPUID_H */
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* CRC16 (CCITT) Checksum Algorithm
|
||||
*
|
||||
* Copyright (c) 2021 Wind River Systems, Inc.
|
||||
*
|
||||
* Author:
|
||||
* Bin Meng <[email protected]>
|
||||
*
|
||||
* From Linux kernel v5.10 include/linux/crc-ccitt.h
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only
|
||||
*/
|
||||
|
||||
#ifndef CRC_CCITT_H
|
||||
#define CRC_CCITT_H
|
||||
|
||||
extern uint16_t const crc_ccitt_table[256];
|
||||
extern uint16_t const crc_ccitt_false_table[256];
|
||||
|
||||
uint16_t crc_ccitt(uint16_t crc, const uint8_t *buffer, size_t len);
|
||||
uint16_t crc_ccitt_false(uint16_t crc, const uint8_t *buffer, size_t len);
|
||||
|
||||
static inline uint16_t crc_ccitt_byte(uint16_t crc, const uint8_t c)
|
||||
{
|
||||
return (crc >> 8) ^ crc_ccitt_table[(crc ^ c) & 0xff];
|
||||
}
|
||||
|
||||
static inline uint16_t crc_ccitt_false_byte(uint16_t crc, const uint8_t c)
|
||||
{
|
||||
return (crc << 8) ^ crc_ccitt_false_table[(crc >> 8) ^ c];
|
||||
}
|
||||
|
||||
#endif /* CRC_CCITT_H */
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* CRC32 Checksum
|
||||
*
|
||||
* Copyright (c) 2026 QEMU contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef QEMU_CRC32_H
|
||||
#define QEMU_CRC32_H
|
||||
|
||||
extern const uint32_t crc32_table[256];
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Castagnoli CRC32C Checksum Algorithm
|
||||
*
|
||||
* Polynomial: 0x11EDC6F41
|
||||
*
|
||||
* Castagnoli93: Guy Castagnoli and Stefan Braeuer and Martin Herrman
|
||||
* "Optimization of Cyclic Redundancy-Check Codes with 24
|
||||
* and 32 Parity Bits",IEEE Transactions on Communication,
|
||||
* Volume 41, Number 6, June 1993
|
||||
*
|
||||
* Copyright (c) 2013 Red Hat, Inc.,
|
||||
*
|
||||
* Authors:
|
||||
* Jeff Cody <[email protected]>
|
||||
*
|
||||
* Based on the Linux kernel cryptographic crc32c module,
|
||||
*
|
||||
* Copyright (c) 2004 Cisco Systems, Inc.
|
||||
* Copyright (c) 2008 Herbert Xu <[email protected]>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QEMU_CRC32C_H
|
||||
#define QEMU_CRC32C_H
|
||||
|
||||
extern const uint32_t crc32c_table[256];
|
||||
|
||||
uint32_t crc32c(uint32_t crc, const uint8_t *data, unsigned int length);
|
||||
uint32_t iov_crc32c(uint32_t crc, const struct iovec *iov, size_t iov_cnt);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* QEMU TCG support
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_CTYPE_H
|
||||
#define QEMU_CTYPE_H
|
||||
|
||||
#define qemu_isalnum(c) isalnum((unsigned char)(c))
|
||||
#define qemu_isalpha(c) isalpha((unsigned char)(c))
|
||||
#define qemu_iscntrl(c) iscntrl((unsigned char)(c))
|
||||
#define qemu_isdigit(c) isdigit((unsigned char)(c))
|
||||
#define qemu_isgraph(c) isgraph((unsigned char)(c))
|
||||
#define qemu_islower(c) islower((unsigned char)(c))
|
||||
#define qemu_isprint(c) isprint((unsigned char)(c))
|
||||
#define qemu_ispunct(c) ispunct((unsigned char)(c))
|
||||
#define qemu_isspace(c) isspace((unsigned char)(c))
|
||||
#define qemu_isupper(c) isupper((unsigned char)(c))
|
||||
#define qemu_isxdigit(c) isxdigit((unsigned char)(c))
|
||||
#define qemu_tolower(c) tolower((unsigned char)(c))
|
||||
#define qemu_toupper(c) toupper((unsigned char)(c))
|
||||
#define qemu_isascii(c) isascii((unsigned char)(c))
|
||||
#define qemu_toascii(c) toascii((unsigned char)(c))
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,305 @@
|
||||
#ifndef QEMU_CUTILS_H
|
||||
#define QEMU_CUTILS_H
|
||||
|
||||
/*
|
||||
* si_prefix:
|
||||
* @exp10: exponent of 10, a multiple of 3 between -18 and 18 inclusive.
|
||||
*
|
||||
* Return a SI prefix (n, u, m, K, M, etc.) corresponding
|
||||
* to the given exponent of 10.
|
||||
*/
|
||||
const char *si_prefix(unsigned int exp10);
|
||||
|
||||
/*
|
||||
* iec_binary_prefix:
|
||||
* @exp2: exponent of 2, a multiple of 10 between 0 and 60 inclusive.
|
||||
*
|
||||
* Return an IEC binary prefix (Ki, Mi, etc.) corresponding
|
||||
* to the given exponent of 2.
|
||||
*/
|
||||
const char *iec_binary_prefix(unsigned int exp2);
|
||||
|
||||
/**
|
||||
* pstrcpy:
|
||||
* @buf: buffer to copy string into
|
||||
* @buf_size: size of @buf in bytes
|
||||
* @str: string to copy
|
||||
*
|
||||
* Copy @str into @buf, including the trailing NUL, but do not
|
||||
* write more than @buf_size bytes. The resulting buffer is
|
||||
* always NUL terminated (even if the source string was too long).
|
||||
* If @buf_size is zero or negative then no bytes are copied.
|
||||
*
|
||||
* This function is similar to strncpy(), but avoids two of that
|
||||
* function's problems:
|
||||
* * if @str fits in the buffer, pstrcpy() does not zero-fill the
|
||||
* remaining space at the end of @buf
|
||||
* * if @str is too long, pstrcpy() will copy the first @buf_size-1
|
||||
* bytes and then add a NUL
|
||||
*/
|
||||
void pstrcpy(char *buf, int buf_size, const char *str);
|
||||
/**
|
||||
* strpadcpy:
|
||||
* @buf: buffer to copy string into
|
||||
* @buf_size: size of @buf in bytes
|
||||
* @str: string to copy
|
||||
* @pad: character to pad the remainder of @buf with
|
||||
*
|
||||
* Copy @str into @buf (but *not* its trailing NUL!), and then pad the
|
||||
* rest of the buffer with the @pad character. If @str is too large
|
||||
* for the buffer then it is truncated, so that @buf contains the
|
||||
* first @buf_size characters of @str, with no terminator.
|
||||
*/
|
||||
void strpadcpy(char *buf, int buf_size, const char *str, char pad);
|
||||
/**
|
||||
* pstrcat:
|
||||
* @buf: buffer containing existing string
|
||||
* @buf_size: size of @buf in bytes
|
||||
* @s: string to concatenate to @buf
|
||||
*
|
||||
* Append a copy of @s to the string already in @buf, but do not
|
||||
* allow the buffer to overflow. If the existing contents of @buf
|
||||
* plus @str would total more than @buf_size bytes, then write
|
||||
* as much of @str as will fit followed by a NUL terminator.
|
||||
*
|
||||
* @buf must already contain a NUL-terminated string, or the
|
||||
* behaviour is undefined.
|
||||
*
|
||||
* Returns: @buf.
|
||||
*/
|
||||
char *pstrcat(char *buf, int buf_size, const char *s);
|
||||
/**
|
||||
* strstart:
|
||||
* @str: string to test
|
||||
* @val: prefix string to look for
|
||||
* @ptr: NULL, or pointer to be written to indicate start of
|
||||
* the remainder of the string
|
||||
*
|
||||
* Test whether @str starts with the prefix @val.
|
||||
* If it does (including the degenerate case where @str and @val
|
||||
* are equal) then return true. If @ptr is not NULL then a
|
||||
* pointer to the first character following the prefix is written
|
||||
* to it. If @val is not a prefix of @str then return false (and
|
||||
* @ptr is not written to).
|
||||
*
|
||||
* Returns: true if @str starts with prefix @val, false otherwise.
|
||||
*/
|
||||
int strstart(const char *str, const char *val, const char **ptr);
|
||||
/**
|
||||
* stristart:
|
||||
* @str: string to test
|
||||
* @val: prefix string to look for
|
||||
* @ptr: NULL, or pointer to be written to indicate start of
|
||||
* the remainder of the string
|
||||
*
|
||||
* Test whether @str starts with the case-insensitive prefix @val.
|
||||
* This function behaves identically to strstart(), except that the
|
||||
* comparison is made after calling qemu_toupper() on each pair of
|
||||
* characters.
|
||||
*
|
||||
* Returns: true if @str starts with case-insensitive prefix @val,
|
||||
* false otherwise.
|
||||
*/
|
||||
int stristart(const char *str, const char *val, const char **ptr);
|
||||
|
||||
/**
|
||||
* qemu_strsep:
|
||||
* @input: pointer to string to parse
|
||||
* @delim: string containing delimiter characters to search for
|
||||
*
|
||||
* Locate the first occurrence of any character in @delim within
|
||||
* the string referenced by @input, and replace it with a NUL.
|
||||
* The location of the next character after the delimiter character
|
||||
* is stored into @input.
|
||||
* If the end of the string was reached without finding a delimiter
|
||||
* character, then NULL is stored into @input.
|
||||
* If @input points to a NULL pointer on entry, return NULL.
|
||||
* The return value is always the original value of *@input (and
|
||||
* so now points to a NUL-terminated string corresponding to the
|
||||
* part of the input up to the first delimiter).
|
||||
*
|
||||
* This function has the same behaviour as the BSD strsep() function.
|
||||
*
|
||||
* Returns: the pointer originally in @input.
|
||||
*/
|
||||
char *qemu_strsep(char **input, const char *delim);
|
||||
#ifdef HAVE_STRCHRNUL
|
||||
static inline const char *qemu_strchrnul(const char *s, int c)
|
||||
{
|
||||
return strchrnul(s, c);
|
||||
}
|
||||
#else
|
||||
const char *qemu_strchrnul(const char *s, int c);
|
||||
#endif
|
||||
time_t mktimegm(struct tm *tm);
|
||||
int qemu_parse_fd(const char *param);
|
||||
int qemu_strtoi(const char *nptr, const char **endptr, int base,
|
||||
int *result);
|
||||
int qemu_strtoui(const char *nptr, const char **endptr, int base,
|
||||
unsigned int *result);
|
||||
int qemu_strtol(const char *nptr, const char **endptr, int base,
|
||||
long *result);
|
||||
int qemu_strtoul(const char *nptr, const char **endptr, int base,
|
||||
unsigned long *result);
|
||||
int qemu_strtoi64(const char *nptr, const char **endptr, int base,
|
||||
int64_t *result);
|
||||
int qemu_strtou64(const char *nptr, const char **endptr, int base,
|
||||
uint64_t *result);
|
||||
int qemu_strtod(const char *nptr, const char **endptr, double *result);
|
||||
int qemu_strtod_finite(const char *nptr, const char **endptr, double *result);
|
||||
|
||||
int parse_uint(const char *s, const char **endptr, int base, uint64_t *value);
|
||||
int parse_uint_full(const char *s, int base, uint64_t *value);
|
||||
|
||||
int qemu_strtosz(const char *nptr, const char **end, uint64_t *result);
|
||||
int qemu_strtosz_MiB(const char *nptr, const char **end, uint64_t *result);
|
||||
int qemu_strtosz_metric(const char *nptr, const char **end, uint64_t *result);
|
||||
|
||||
char *size_to_str(uint64_t val);
|
||||
|
||||
/**
|
||||
* freq_to_str:
|
||||
* @freq_hz: frequency to stringify
|
||||
*
|
||||
* Return human readable string for frequency @freq_hz.
|
||||
* Use SI units like KHz, MHz, and so forth.
|
||||
*
|
||||
* The caller is responsible for releasing the value returned
|
||||
* with g_free() after use.
|
||||
*/
|
||||
char *freq_to_str(uint64_t freq_hz);
|
||||
|
||||
/* used to print char* safely */
|
||||
#define STR_OR_NULL(str) ((str) ? (str) : "null")
|
||||
|
||||
/*
|
||||
* Check if a buffer is all zeroes.
|
||||
*/
|
||||
|
||||
bool buffer_is_zero_ool(const void *vbuf, size_t len);
|
||||
bool buffer_is_zero_ge256(const void *vbuf, size_t len);
|
||||
bool test_buffer_is_zero_next_accel(void);
|
||||
|
||||
static inline bool buffer_is_zero_sample3(const char *buf, size_t len)
|
||||
{
|
||||
/*
|
||||
* For any reasonably sized buffer, these three samples come from
|
||||
* three different cachelines. In qemu-img usage, we find that
|
||||
* each byte eliminates more than half of all buffer testing.
|
||||
* It is therefore critical to performance that the byte tests
|
||||
* short-circuit, so that we do not pull in additional cache lines.
|
||||
* Do not "optimize" this to !(a | b | c).
|
||||
*/
|
||||
return !buf[0] && !buf[len - 1] && !buf[len / 2];
|
||||
}
|
||||
|
||||
#ifdef __OPTIMIZE__
|
||||
static inline bool buffer_is_zero(const void *buf, size_t len)
|
||||
{
|
||||
return (__builtin_constant_p(len) && len >= 256
|
||||
? buffer_is_zero_sample3(buf, len) &&
|
||||
buffer_is_zero_ge256(buf, len)
|
||||
: buffer_is_zero_ool(buf, len));
|
||||
}
|
||||
#else
|
||||
#define buffer_is_zero buffer_is_zero_ool
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Implementation of ULEB128 (http://en.wikipedia.org/wiki/LEB128)
|
||||
* Input is limited to 14-bit numbers
|
||||
*/
|
||||
|
||||
int uleb128_encode_small(uint8_t *out, uint32_t n);
|
||||
int uleb128_decode_small(const uint8_t *in, uint32_t *n);
|
||||
|
||||
/**
|
||||
* qemu_pstrcmp0:
|
||||
* @str1: a non-NULL pointer to a C string (*str1 can be NULL)
|
||||
* @str2: a non-NULL pointer to a C string (*str2 can be NULL)
|
||||
*
|
||||
* Compares *str1 and *str2 with g_strcmp0().
|
||||
*
|
||||
* Returns: an integer less than, equal to, or greater than zero, if
|
||||
* *str1 is <, == or > than *str2.
|
||||
*/
|
||||
int qemu_pstrcmp0(const char **str1, const char **str2);
|
||||
|
||||
/* Find program directory, and save it for later usage with
|
||||
* get_relocated_path().
|
||||
* Try OS specific API first, if not working, parse from argv0. */
|
||||
void qemu_init_exec_dir(const char *argv0);
|
||||
|
||||
/**
|
||||
* get_relocated_path:
|
||||
* @dir: the directory (typically a `CONFIG_*DIR` variable) to be relocated.
|
||||
*
|
||||
* Returns a path for @dir that uses the directory of the running executable
|
||||
* as the prefix.
|
||||
*
|
||||
* When a directory named `qemu-bundle` exists in the directory of the running
|
||||
* executable, the path to the directory will be prepended to @dir. For
|
||||
* example, if the directory of the running executable is `/qemu/build` @dir
|
||||
* is `/usr/share/qemu`, the result will be
|
||||
* `/qemu/build/qemu-bundle/usr/share/qemu`. The directory is expected to exist
|
||||
* in the build tree.
|
||||
*
|
||||
* Otherwise, the directory of the running executable will be used as the
|
||||
* prefix and it appends the relative path from `bindir` to @dir. For example,
|
||||
* if the directory of the running executable is `/opt/qemu/bin`, `bindir` is
|
||||
* `/usr/bin` and @dir is `/usr/share/qemu`, the result will be
|
||||
* `/opt/qemu/bin/../share/qemu`.
|
||||
*
|
||||
* The returned string should be freed by the caller.
|
||||
*/
|
||||
char *get_relocated_path(const char *dir);
|
||||
|
||||
static inline const char *yes_no(bool b)
|
||||
{
|
||||
return b ? "yes" : "no";
|
||||
}
|
||||
|
||||
/*
|
||||
* helper to parse debug environment variables
|
||||
*/
|
||||
int parse_debug_env(const char *name, int max, int initial);
|
||||
|
||||
/**
|
||||
* qemu_hexdump_line:
|
||||
* @str: GString into which to append
|
||||
* @buf: buffer to dump
|
||||
* @len: number of bytes to dump
|
||||
* @unit_len: add a space between every @unit_len bytes
|
||||
* @block_len: add an extra space between every @block_len bytes
|
||||
*
|
||||
* Append @len bytes of @buf as hexadecimal into @str.
|
||||
* Add spaces between every @unit_len and @block_len bytes.
|
||||
* If @str is NULL, allocate a new string and return it;
|
||||
* otherwise return @str.
|
||||
*/
|
||||
GString *qemu_hexdump_line(GString *str, const void *buf, size_t len,
|
||||
size_t unit_len, size_t block_len);
|
||||
|
||||
/*
|
||||
* Hexdump a buffer to a file. An optional string prefix is added to every line
|
||||
*/
|
||||
|
||||
void qemu_hexdump(FILE *fp, const char *prefix,
|
||||
const void *bufptr, size_t size);
|
||||
|
||||
/**
|
||||
* qemu_hexdump_to_buffer:
|
||||
* @buffer: output string buffer
|
||||
* @buffer_size: amount of available space in buffer. Must be at least
|
||||
* data_size*2+1.
|
||||
* @data: input bytes
|
||||
* @data_size: number of bytes in data
|
||||
*
|
||||
* Converts the @data_size bytes in @data into hex digit pairs, writing them to
|
||||
* @buffer. Finally, a nul terminating character is written; @buffer therefore
|
||||
* needs space for (data_size*2+1) chars.
|
||||
*/
|
||||
void qemu_hexdump_to_buffer(char *restrict buffer, size_t buffer_size,
|
||||
const uint8_t *restrict data, size_t data_size);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,33 @@
|
||||
#ifndef QEMU_DATADIR_H
|
||||
#define QEMU_DATADIR_H
|
||||
|
||||
typedef enum {
|
||||
QEMU_FILE_TYPE_BIOS,
|
||||
QEMU_FILE_TYPE_DTB,
|
||||
QEMU_FILE_TYPE_KEYMAP,
|
||||
} QemuFileType;
|
||||
|
||||
/**
|
||||
* qemu_find_file:
|
||||
* @type: QEMU_FILE_TYPE_BIOS (for BIOS, VGA BIOS)
|
||||
* QEMU_FILE_TYPE_DTB (for device tree blobs)
|
||||
* or QEMU_FILE_TYPE_KEYMAP (for keymaps).
|
||||
* @name: Relative or absolute file name
|
||||
*
|
||||
* If @name exists on disk as an absolute path, or a path relative
|
||||
* to the current directory, then returns @name unchanged.
|
||||
* Otherwise searches for @name file in the data directories, either
|
||||
* configured at build time (DATADIR) or registered with the -L command
|
||||
* line option.
|
||||
*
|
||||
* The caller must use g_free() to free the returned data when it is
|
||||
* no longer required.
|
||||
*
|
||||
* Returns: a path that can access @name, or NULL if no matching file exists.
|
||||
*/
|
||||
char *qemu_find_file(QemuFileType type, const char *name);
|
||||
void qemu_add_default_firmwarepath(void);
|
||||
void qemu_add_data_dir(char *path);
|
||||
void qemu_list_data_dirs(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Helpers for using D-Bus
|
||||
*
|
||||
* Copyright (C) 2019 Red Hat, Inc.
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef DBUS_H
|
||||
#define DBUS_H
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "qom/object.h"
|
||||
#include "chardev/char.h"
|
||||
#include "qemu/notify.h"
|
||||
|
||||
/* glib/gio 2.68 */
|
||||
#define DBUS_METHOD_INVOCATION_HANDLED TRUE
|
||||
#define DBUS_METHOD_INVOCATION_UNHANDLED FALSE
|
||||
|
||||
/* in msec */
|
||||
#define DBUS_DEFAULT_TIMEOUT 1000
|
||||
|
||||
#define DBUS_DISPLAY1_ROOT "/org/qemu/Display1"
|
||||
|
||||
#define DBUS_DISPLAY_ERROR (dbus_display_error_quark())
|
||||
GQuark dbus_display_error_quark(void);
|
||||
|
||||
typedef enum {
|
||||
DBUS_DISPLAY_ERROR_FAILED,
|
||||
DBUS_DISPLAY_ERROR_INVALID,
|
||||
DBUS_DISPLAY_ERROR_UNSUPPORTED,
|
||||
DBUS_DISPLAY_N_ERRORS,
|
||||
} DBusDisplayError;
|
||||
|
||||
GStrv qemu_dbus_get_queued_owners(GDBusConnection *connection,
|
||||
const char *name,
|
||||
Error **errp);
|
||||
|
||||
#endif /* DBUS_H */
|
||||
@@ -0,0 +1,16 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Deferred calls
|
||||
*
|
||||
* Copyright Red Hat.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_DEFER_CALL_H
|
||||
#define QEMU_DEFER_CALL_H
|
||||
|
||||
/* See documentation in util/defer-call.c */
|
||||
void defer_call_begin(void);
|
||||
void defer_call_end(void);
|
||||
void defer_call(void (*fn)(void *), void *opaque);
|
||||
|
||||
#endif /* QEMU_DEFER_CALL_H */
|
||||
@@ -0,0 +1,6 @@
|
||||
#ifndef QEMU_DRM_H
|
||||
#define QEMU_DRM_H
|
||||
|
||||
int qemu_drm_rendernode_open(const char *rendernode);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef ENVLIST_H
|
||||
#define ENVLIST_H
|
||||
|
||||
typedef struct envlist envlist_t;
|
||||
|
||||
envlist_t *envlist_create(void);
|
||||
void envlist_free(envlist_t *);
|
||||
int envlist_setenv(envlist_t *, const char *);
|
||||
int envlist_unsetenv(envlist_t *, const char *);
|
||||
char **envlist_to_environ(const envlist_t *, size_t *);
|
||||
|
||||
#endif /* ENVLIST_H */
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Error reporting
|
||||
*
|
||||
* Copyright (C) 2010 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Markus Armbruster <[email protected]>,
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_ERROR_REPORT_H
|
||||
#define QEMU_ERROR_REPORT_H
|
||||
|
||||
typedef struct Location {
|
||||
/* all members are private to qemu-error.c */
|
||||
enum { LOC_NONE, LOC_CMDLINE, LOC_FILE } kind;
|
||||
int num;
|
||||
const void *ptr;
|
||||
struct Location *prev;
|
||||
} Location;
|
||||
|
||||
Location *loc_push_restore(Location *loc);
|
||||
Location *loc_push_none(Location *loc);
|
||||
Location *loc_pop(Location *loc);
|
||||
Location *loc_save(Location *loc);
|
||||
void loc_restore(Location *loc);
|
||||
void loc_set_none(void);
|
||||
void loc_set_cmdline(char **argv, int idx, int cnt);
|
||||
void loc_set_file(const char *fname, int lno);
|
||||
|
||||
int error_vprintf(const char *fmt, va_list ap) G_GNUC_PRINTF(1, 0);
|
||||
int error_printf(const char *fmt, ...) G_GNUC_PRINTF(1, 2);
|
||||
|
||||
void error_vreport(const char *fmt, va_list ap) G_GNUC_PRINTF(1, 0);
|
||||
void warn_vreport(const char *fmt, va_list ap) G_GNUC_PRINTF(1, 0);
|
||||
void info_vreport(const char *fmt, va_list ap) G_GNUC_PRINTF(1, 0);
|
||||
|
||||
void error_report(const char *fmt, ...) G_GNUC_PRINTF(1, 2);
|
||||
void warn_report(const char *fmt, ...) G_GNUC_PRINTF(1, 2);
|
||||
void info_report(const char *fmt, ...) G_GNUC_PRINTF(1, 2);
|
||||
|
||||
bool error_report_once_cond(bool *printed, const char *fmt, ...)
|
||||
G_GNUC_PRINTF(2, 3);
|
||||
bool warn_report_once_cond(bool *printed, const char *fmt, ...)
|
||||
G_GNUC_PRINTF(2, 3);
|
||||
|
||||
void error_init(const char *argv0);
|
||||
|
||||
/*
|
||||
* Similar to error_report(), except it prints the message just once.
|
||||
* Return true when it prints, false otherwise.
|
||||
*/
|
||||
#define error_report_once(fmt, ...) \
|
||||
({ \
|
||||
static bool print_once_; \
|
||||
error_report_once_cond(&print_once_, \
|
||||
fmt, ##__VA_ARGS__); \
|
||||
})
|
||||
|
||||
/*
|
||||
* Similar to warn_report(), except it prints the message just once.
|
||||
* Return true when it prints, false otherwise.
|
||||
*/
|
||||
#define warn_report_once(fmt, ...) \
|
||||
({ \
|
||||
static bool print_once_; \
|
||||
warn_report_once_cond(&print_once_, \
|
||||
fmt, ##__VA_ARGS__); \
|
||||
})
|
||||
|
||||
extern bool message_with_timestamp;
|
||||
extern bool error_with_guestname;
|
||||
extern const char *error_guest_name;
|
||||
|
||||
/*
|
||||
* Return current datetime in ISO 8601 format.
|
||||
* Caller is responsible to g_free() the returned string.
|
||||
*/
|
||||
char *real_time_iso8601(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* event notifier support
|
||||
*
|
||||
* Copyright Red Hat, Inc. 2010
|
||||
*
|
||||
* Authors:
|
||||
* Michael S. Tsirkin <[email protected]>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_EVENT_NOTIFIER_H
|
||||
#define QEMU_EVENT_NOTIFIER_H
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
struct EventNotifier {
|
||||
#ifdef _WIN32
|
||||
HANDLE event;
|
||||
#else
|
||||
int rfd;
|
||||
int wfd;
|
||||
bool initialized;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef void EventNotifierHandler(EventNotifier *);
|
||||
|
||||
int event_notifier_init(EventNotifier *, int active);
|
||||
void event_notifier_cleanup(EventNotifier *);
|
||||
int event_notifier_set(EventNotifier *);
|
||||
int event_notifier_test_and_clear(EventNotifier *);
|
||||
|
||||
#ifdef CONFIG_POSIX
|
||||
void event_notifier_init_fd(EventNotifier *, int fd);
|
||||
int event_notifier_get_fd(const EventNotifier *);
|
||||
int event_notifier_get_wfd(const EventNotifier *);
|
||||
#else
|
||||
HANDLE event_notifier_get_handle(EventNotifier *);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* Originally derived from nbdkit common/utils/exit-with-parent.h
|
||||
* Copyright Red Hat
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of Red Hat nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef NBDKIT_EXIT_WITH_PARENT_H
|
||||
#define NBDKIT_EXIT_WITH_PARENT_H
|
||||
|
||||
/* Test if the feature is available on the platform. */
|
||||
static inline bool can_exit_with_parent(void)
|
||||
{
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* --exit-with-parent: kill the current process if the parent exits.
|
||||
* This may return -1 on error.
|
||||
*
|
||||
* Note this will abort on platforms where can_exit_with_parent()
|
||||
* returned false.
|
||||
*/
|
||||
extern int set_exit_with_parent(void);
|
||||
|
||||
#endif /* NBDKIT_EXIT_WITH_PARENT_H */
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Generic FIFO32 component, based on FIFO8.
|
||||
*
|
||||
* Copyright (c) 2016 Jean-Christophe Dubois
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef FIFO32_H
|
||||
#define FIFO32_H
|
||||
|
||||
#include "qemu/fifo8.h"
|
||||
|
||||
typedef struct {
|
||||
Fifo8 fifo;
|
||||
} Fifo32;
|
||||
|
||||
/**
|
||||
* fifo32_create:
|
||||
* @fifo: struct Fifo32 to initialise with new FIFO
|
||||
* @capacity: capacity of the newly created FIFO expressed in 32 bit words
|
||||
*
|
||||
* Create a FIFO of the specified size. Clients should call fifo32_destroy()
|
||||
* when finished using the fifo. The FIFO is initially empty.
|
||||
*/
|
||||
|
||||
static inline void fifo32_create(Fifo32 *fifo, uint32_t capacity)
|
||||
{
|
||||
fifo8_create(&fifo->fifo, capacity * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
/**
|
||||
* fifo32_destroy:
|
||||
* @fifo: FIFO to cleanup
|
||||
*
|
||||
* Cleanup a FIFO created with fifo32_create(). Frees memory created for FIFO
|
||||
* storage. The FIFO is no longer usable after this has been called.
|
||||
*/
|
||||
|
||||
static inline void fifo32_destroy(Fifo32 *fifo)
|
||||
{
|
||||
fifo8_destroy(&fifo->fifo);
|
||||
}
|
||||
|
||||
/**
|
||||
* fifo32_num_free:
|
||||
* @fifo: FIFO to check
|
||||
*
|
||||
* Return the number of free uint32_t slots in the FIFO.
|
||||
*
|
||||
* Returns: Number of free 32 bit words.
|
||||
*/
|
||||
|
||||
static inline uint32_t fifo32_num_free(Fifo32 *fifo)
|
||||
{
|
||||
return DIV_ROUND_UP(fifo8_num_free(&fifo->fifo), sizeof(uint32_t));
|
||||
}
|
||||
|
||||
/**
|
||||
* fifo32_num_used:
|
||||
* @fifo: FIFO to check
|
||||
*
|
||||
* Return the number of used uint32_t slots in the FIFO.
|
||||
*
|
||||
* Returns: Number of used 32 bit words.
|
||||
*/
|
||||
|
||||
static inline uint32_t fifo32_num_used(Fifo32 *fifo)
|
||||
{
|
||||
return DIV_ROUND_UP(fifo8_num_used(&fifo->fifo), sizeof(uint32_t));
|
||||
}
|
||||
|
||||
/**
|
||||
* fifo32_push:
|
||||
* @fifo: FIFO to push to
|
||||
* @data: 32 bits data word to push
|
||||
*
|
||||
* Push a 32 bits data word to the FIFO. Behaviour is undefined if the FIFO
|
||||
* is full. Clients are responsible for checking for fullness using
|
||||
* fifo32_is_full().
|
||||
*/
|
||||
|
||||
static inline void fifo32_push(Fifo32 *fifo, uint32_t data)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(data); i++) {
|
||||
fifo8_push(&fifo->fifo, data & 0xff);
|
||||
data >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fifo32_push_all:
|
||||
* @fifo: FIFO to push to
|
||||
* @data: data to push
|
||||
* @size: number of 32 bit words to push
|
||||
*
|
||||
* Push a 32 bit word array to the FIFO. Behaviour is undefined if the FIFO
|
||||
* is full. Clients are responsible for checking the space left in the FIFO
|
||||
* using fifo32_num_free().
|
||||
*/
|
||||
|
||||
static inline void fifo32_push_all(Fifo32 *fifo, const uint32_t *data,
|
||||
uint32_t num)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
fifo32_push(fifo, data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fifo32_pop:
|
||||
* @fifo: fifo to pop from
|
||||
*
|
||||
* Pop a 32 bits data word from the FIFO. Behaviour is undefined if the FIFO
|
||||
* is empty. Clients are responsible for checking for emptiness using
|
||||
* fifo32_is_empty().
|
||||
*
|
||||
* Returns: The popped 32 bits data word.
|
||||
*/
|
||||
|
||||
static inline uint32_t fifo32_pop(Fifo32 *fifo)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(uint32_t); i++) {
|
||||
ret |= (fifo8_pop(&fifo->fifo) << (i * 8));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* There is no fifo32_pop_buf() because the data is not stored in the buffer
|
||||
* as a set of native-order words.
|
||||
*/
|
||||
|
||||
/**
|
||||
* fifo32_reset:
|
||||
* @fifo: FIFO to reset
|
||||
*
|
||||
* Reset a FIFO. All data is discarded and the FIFO is emptied.
|
||||
*/
|
||||
|
||||
static inline void fifo32_reset(Fifo32 *fifo)
|
||||
{
|
||||
fifo8_reset(&fifo->fifo);
|
||||
}
|
||||
|
||||
/**
|
||||
* fifo32_is_empty:
|
||||
* @fifo: FIFO to check
|
||||
*
|
||||
* Check if a FIFO is empty.
|
||||
*
|
||||
* Returns: True if the fifo is empty, false otherwise.
|
||||
*/
|
||||
|
||||
static inline bool fifo32_is_empty(Fifo32 *fifo)
|
||||
{
|
||||
return fifo8_is_empty(&fifo->fifo);
|
||||
}
|
||||
|
||||
/**
|
||||
* fifo32_is_full:
|
||||
* @fifo: FIFO to check
|
||||
*
|
||||
* Check if a FIFO is full.
|
||||
*
|
||||
* Returns: True if the fifo is full, false otherwise.
|
||||
*/
|
||||
|
||||
static inline bool fifo32_is_full(Fifo32 *fifo)
|
||||
{
|
||||
return fifo8_num_free(&fifo->fifo) < sizeof(uint32_t);
|
||||
}
|
||||
|
||||
#define VMSTATE_FIFO32(_field, _state) VMSTATE_FIFO8(_field.fifo, _state)
|
||||
|
||||
#endif /* FIFO32_H */
|
||||
@@ -0,0 +1,230 @@
|
||||
#ifndef QEMU_FIFO8_H
|
||||
#define QEMU_FIFO8_H
|
||||
|
||||
|
||||
typedef struct {
|
||||
/* All fields are private */
|
||||
uint8_t *data;
|
||||
uint32_t capacity;
|
||||
uint32_t head;
|
||||
uint32_t num;
|
||||
} Fifo8;
|
||||
|
||||
/**
|
||||
* fifo8_create:
|
||||
* @fifo: struct Fifo8 to initialise with new FIFO
|
||||
* @capacity: capacity of the newly created FIFO
|
||||
*
|
||||
* Create a FIFO of the specified capacity. Clients should call fifo8_destroy()
|
||||
* when finished using the fifo. The FIFO is initially empty.
|
||||
*/
|
||||
void fifo8_create(Fifo8 *fifo, uint32_t capacity);
|
||||
|
||||
/**
|
||||
* fifo8_destroy:
|
||||
* @fifo: FIFO to cleanup
|
||||
*
|
||||
* Cleanup a FIFO created with fifo8_create(). Frees memory created for FIFO
|
||||
* storage. The FIFO is no longer usable after this has been called.
|
||||
*/
|
||||
void fifo8_destroy(Fifo8 *fifo);
|
||||
|
||||
/**
|
||||
* fifo8_push:
|
||||
* @fifo: FIFO to push to
|
||||
* @data: data byte to push
|
||||
*
|
||||
* Push a data byte to the FIFO. Behaviour is undefined if the FIFO is full.
|
||||
* Clients are responsible for checking for fullness using fifo8_is_full().
|
||||
*/
|
||||
void fifo8_push(Fifo8 *fifo, uint8_t data);
|
||||
|
||||
/**
|
||||
* fifo8_push_all:
|
||||
* @fifo: FIFO to push to
|
||||
* @data: data to push
|
||||
* @num: number of bytes to push
|
||||
*
|
||||
* Push a byte array to the FIFO. Behaviour is undefined if the FIFO is full.
|
||||
* Clients are responsible for checking the space left in the FIFO using
|
||||
* fifo8_num_free().
|
||||
*/
|
||||
void fifo8_push_all(Fifo8 *fifo, const uint8_t *data, uint32_t num);
|
||||
|
||||
/**
|
||||
* fifo8_pop:
|
||||
* @fifo: fifo to pop from
|
||||
*
|
||||
* Pop a data byte from the FIFO. Behaviour is undefined if the FIFO is empty.
|
||||
* Clients are responsible for checking for emptyness using fifo8_is_empty().
|
||||
*
|
||||
* Returns: The popped data byte.
|
||||
*/
|
||||
uint8_t fifo8_pop(Fifo8 *fifo);
|
||||
|
||||
/**
|
||||
* fifo8_peek:
|
||||
* @fifo: fifo to peek from
|
||||
*
|
||||
* Peek the data byte at the current head of the FIFO. Clients are responsible
|
||||
* for checking for emptyness using fifo8_is_empty().
|
||||
*
|
||||
* Returns: The peeked data byte.
|
||||
*/
|
||||
uint8_t fifo8_peek(const Fifo8 *fifo);
|
||||
|
||||
/**
|
||||
* fifo8_pop_buf:
|
||||
* @fifo: FIFO to pop from
|
||||
* @dest: the buffer to write the data into (can be NULL)
|
||||
* @destlen: size of @dest and maximum number of bytes to pop
|
||||
*
|
||||
* Pop a number of elements from the FIFO up to a maximum of @destlen.
|
||||
* The popped data is copied into the @dest buffer.
|
||||
* Care is taken when the data wraps around in the ring buffer.
|
||||
*
|
||||
* Returns: number of bytes popped.
|
||||
*/
|
||||
uint32_t fifo8_pop_buf(Fifo8 *fifo, uint8_t *dest, uint32_t destlen);
|
||||
|
||||
/**
|
||||
* fifo8_peek_buf:
|
||||
* @fifo: FIFO to read from
|
||||
* @dest: the buffer to write the data into (can be NULL)
|
||||
* @destlen: size of @dest and maximum number of bytes to peek
|
||||
*
|
||||
* Peek a number of elements from the FIFO up to a maximum of @destlen.
|
||||
* The peeked data is copied into the @dest buffer.
|
||||
* Care is taken when the data wraps around in the ring buffer.
|
||||
*
|
||||
* Returns: number of bytes peeked.
|
||||
*/
|
||||
uint32_t fifo8_peek_buf(Fifo8 *fifo, uint8_t *dest, uint32_t destlen);
|
||||
|
||||
/**
|
||||
* fifo8_pop_bufptr:
|
||||
* @fifo: FIFO to pop from
|
||||
* @max: maximum number of bytes to pop
|
||||
* @numptr: pointer filled with number of bytes returned (can be NULL)
|
||||
*
|
||||
* New code should prefer to use fifo8_pop_buf() instead of fifo8_pop_bufptr().
|
||||
*
|
||||
* Pop a number of elements from the FIFO up to a maximum of @max. The buffer
|
||||
* containing the popped data is returned. This buffer points directly into
|
||||
* the internal FIFO backing store and data (without checking for overflow!)
|
||||
* and is invalidated once any of the fifo8_* APIs are called on the FIFO.
|
||||
*
|
||||
* The function may return fewer bytes than requested when the data wraps
|
||||
* around in the ring buffer; in this case only a contiguous part of the data
|
||||
* is returned.
|
||||
*
|
||||
* The number of valid bytes returned is populated in *@numptr; will always
|
||||
* return at least 1 byte. max must not be 0 or greater than the number of
|
||||
* bytes in the FIFO.
|
||||
*
|
||||
* Clients are responsible for checking the availability of requested data
|
||||
* using fifo8_num_used().
|
||||
*
|
||||
* Returns: A pointer to popped data.
|
||||
*/
|
||||
const uint8_t *fifo8_pop_bufptr(Fifo8 *fifo, uint32_t max, uint32_t *numptr);
|
||||
|
||||
/**
|
||||
* fifo8_peek_bufptr: read upto max bytes from the fifo
|
||||
* @fifo: FIFO to read from
|
||||
* @max: maximum number of bytes to peek
|
||||
* @numptr: pointer filled with number of bytes returned (can be NULL)
|
||||
*
|
||||
* Peek into a number of elements from the FIFO up to a maximum of @max.
|
||||
* The buffer containing the data peeked into is returned. This buffer points
|
||||
* directly into the FIFO backing store. Since data is invalidated once any
|
||||
* of the fifo8_* APIs are called on the FIFO, it is the caller responsibility
|
||||
* to access it before doing further API calls.
|
||||
*
|
||||
* The function may return fewer bytes than requested when the data wraps
|
||||
* around in the ring buffer; in this case only a contiguous part of the data
|
||||
* is returned.
|
||||
*
|
||||
* The number of valid bytes returned is populated in *@numptr; will always
|
||||
* return at least 1 byte. max must not be 0 or greater than the number of
|
||||
* bytes in the FIFO.
|
||||
*
|
||||
* Clients are responsible for checking the availability of requested data
|
||||
* using fifo8_num_used().
|
||||
*
|
||||
* Returns: A pointer to peekable data.
|
||||
*/
|
||||
const uint8_t *fifo8_peek_bufptr(Fifo8 *fifo, uint32_t max, uint32_t *numptr);
|
||||
|
||||
/**
|
||||
* fifo8_drop:
|
||||
* @fifo: FIFO to drop bytes
|
||||
* @len: number of bytes to drop
|
||||
*
|
||||
* Drop (consume) bytes from a FIFO.
|
||||
*/
|
||||
void fifo8_drop(Fifo8 *fifo, uint32_t len);
|
||||
|
||||
/**
|
||||
* fifo8_reset:
|
||||
* @fifo: FIFO to reset
|
||||
*
|
||||
* Reset a FIFO. All data is discarded and the FIFO is emptied.
|
||||
*/
|
||||
void fifo8_reset(Fifo8 *fifo);
|
||||
|
||||
/**
|
||||
* fifo8_is_empty:
|
||||
* @fifo: FIFO to check
|
||||
*
|
||||
* Check if a FIFO is empty.
|
||||
*
|
||||
* Returns: True if the fifo is empty, false otherwise.
|
||||
*/
|
||||
bool fifo8_is_empty(const Fifo8 *fifo);
|
||||
|
||||
/**
|
||||
* fifo8_is_full:
|
||||
* @fifo: FIFO to check
|
||||
*
|
||||
* Check if a FIFO is full.
|
||||
*
|
||||
* Returns: True if the fifo is full, false otherwise.
|
||||
*/
|
||||
bool fifo8_is_full(const Fifo8 *fifo);
|
||||
|
||||
/**
|
||||
* fifo8_num_free:
|
||||
* @fifo: FIFO to check
|
||||
*
|
||||
* Return the number of free bytes in the FIFO.
|
||||
*
|
||||
* Returns: Number of free bytes.
|
||||
*/
|
||||
uint32_t fifo8_num_free(const Fifo8 *fifo);
|
||||
|
||||
/**
|
||||
* fifo8_num_used:
|
||||
* @fifo: FIFO to check
|
||||
*
|
||||
* Return the number of used bytes in the FIFO.
|
||||
*
|
||||
* Returns: Number of used bytes.
|
||||
*/
|
||||
uint32_t fifo8_num_used(const Fifo8 *fifo);
|
||||
|
||||
extern const VMStateDescription vmstate_fifo8;
|
||||
|
||||
#define VMSTATE_FIFO8_TEST(_field, _state, _test) { \
|
||||
.name = (stringify(_field)), \
|
||||
.field_exists = (_test), \
|
||||
.size = sizeof(Fifo8), \
|
||||
.vmsd = &vmstate_fifo8, \
|
||||
.flags = VMS_STRUCT, \
|
||||
.offset = vmstate_offset_value(_state, _field, Fifo8), \
|
||||
}
|
||||
|
||||
#define VMSTATE_FIFO8(_field, _state) \
|
||||
VMSTATE_FIFO8_TEST(_field, _state, NULL)
|
||||
|
||||
#endif /* QEMU_FIFO8_H */
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* QEMU file monitor helper
|
||||
*
|
||||
* Copyright (c) 2018 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QEMU_FILEMONITOR_H
|
||||
#define QEMU_FILEMONITOR_H
|
||||
|
||||
|
||||
|
||||
typedef struct QFileMonitor QFileMonitor;
|
||||
|
||||
typedef enum {
|
||||
/* File has been created in a dir */
|
||||
QFILE_MONITOR_EVENT_CREATED,
|
||||
/* File has been modified in a dir */
|
||||
QFILE_MONITOR_EVENT_MODIFIED,
|
||||
/* File has been deleted in a dir */
|
||||
QFILE_MONITOR_EVENT_DELETED,
|
||||
/* File has attributes changed */
|
||||
QFILE_MONITOR_EVENT_ATTRIBUTES,
|
||||
/* Dir is no longer being monitored (due to deletion) */
|
||||
QFILE_MONITOR_EVENT_IGNORED,
|
||||
} QFileMonitorEvent;
|
||||
|
||||
|
||||
/**
|
||||
* QFileMonitorHandler:
|
||||
* @id: id from qemu_file_monitor_add_watch()
|
||||
* @event: the file change that occurred
|
||||
* @filename: the name of the file affected
|
||||
* @opaque: opaque data provided to qemu_file_monitor_add_watch()
|
||||
*
|
||||
* Invoked whenever a file changes. If @event is
|
||||
* QFILE_MONITOR_EVENT_IGNORED, @filename will be
|
||||
* empty.
|
||||
*
|
||||
*/
|
||||
typedef void (*QFileMonitorHandler)(int64_t id,
|
||||
QFileMonitorEvent event,
|
||||
const char *filename,
|
||||
void *opaque);
|
||||
|
||||
/**
|
||||
* qemu_file_monitor_new:
|
||||
* @errp: pointer to a NULL-initialized error object
|
||||
*
|
||||
* Create a handle for a file monitoring object.
|
||||
*
|
||||
* This object does locking internally to enable it to be
|
||||
* safe to use from multiple threads
|
||||
*
|
||||
* If the platform does not support file monitoring, an
|
||||
* error will be reported. Likewise if file monitoring
|
||||
* is supported, but cannot be initialized
|
||||
*
|
||||
* Currently this is implemented on Linux platforms with
|
||||
* the inotify subsystem.
|
||||
*
|
||||
* Returns: the new monitoring object, or NULL on error
|
||||
*/
|
||||
QFileMonitor *qemu_file_monitor_new(Error **errp);
|
||||
|
||||
/**
|
||||
* qemu_file_monitor_free:
|
||||
* @mon: the file monitor context
|
||||
*
|
||||
* Free resources associated with the file monitor,
|
||||
* including any currently registered watches.
|
||||
*/
|
||||
void qemu_file_monitor_free(QFileMonitor *mon);
|
||||
|
||||
/**
|
||||
* qemu_file_monitor_add_watch:
|
||||
* @mon: the file monitor context
|
||||
* @dirpath: the directory whose contents to watch
|
||||
* @filename: optional filename to filter on
|
||||
* @cb: the function to invoke when @dirpath has changes
|
||||
* @opaque: data to pass to @cb
|
||||
* @errp: pointer to a NULL-initialized error object
|
||||
*
|
||||
* Register to receive notifications of changes
|
||||
* in the directory @dirpath. All files in the
|
||||
* directory will be monitored. If the caller is
|
||||
* only interested in one specific file, @filename
|
||||
* can be used to filter events.
|
||||
*
|
||||
* Returns: a positive integer watch ID, or -1 on error
|
||||
*/
|
||||
int64_t qemu_file_monitor_add_watch(QFileMonitor *mon,
|
||||
const char *dirpath,
|
||||
const char *filename,
|
||||
QFileMonitorHandler cb,
|
||||
void *opaque,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* qemu_file_monitor_remove_watch:
|
||||
* @mon: the file monitor context
|
||||
* @dirpath: the directory whose contents to unwatch
|
||||
* @id: id of the watch to remove
|
||||
*
|
||||
* Removes the file monitoring watch @id, associated
|
||||
* with the directory @dirpath. This must never be
|
||||
* called from a QFileMonitorHandler callback, or a
|
||||
* deadlock will result.
|
||||
*/
|
||||
void qemu_file_monitor_remove_watch(QFileMonitor *mon,
|
||||
const char *dirpath,
|
||||
int64_t id);
|
||||
|
||||
#endif /* QEMU_FILEMONITOR_H */
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Wrappers around Linux futex syscall and similar
|
||||
*
|
||||
* Copyright Red Hat, Inc. 2017
|
||||
*
|
||||
* Author:
|
||||
* Paolo Bonzini <[email protected]>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Note that a wake-up can also be caused by common futex usage patterns in
|
||||
* unrelated code that happened to have previously used the futex word's
|
||||
* memory location (e.g., typical futex-based implementations of Pthreads
|
||||
* mutexes can cause this under some conditions). Therefore, qemu_futex_wait()
|
||||
* callers should always conservatively assume that it is a spurious wake-up,
|
||||
* and use the futex word's value (i.e., the user-space synchronization scheme)
|
||||
* to decide whether to continue to block or not.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_FUTEX_H
|
||||
#define QEMU_FUTEX_H
|
||||
|
||||
#define HAVE_FUTEX
|
||||
|
||||
#ifdef CONFIG_LINUX
|
||||
#include <sys/syscall.h>
|
||||
#include <linux/futex.h>
|
||||
|
||||
#define qemu_futex(...) syscall(__NR_futex, __VA_ARGS__)
|
||||
|
||||
static inline void qemu_futex_wake_all(void *f)
|
||||
{
|
||||
qemu_futex(f, FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
static inline void qemu_futex_wake_single(void *f)
|
||||
{
|
||||
qemu_futex(f, FUTEX_WAKE, 1, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
static inline void qemu_futex_wait(void *f, unsigned val)
|
||||
{
|
||||
while (qemu_futex(f, FUTEX_WAIT, (int) val, NULL, NULL, 0)) {
|
||||
switch (errno) {
|
||||
case EWOULDBLOCK:
|
||||
return;
|
||||
case EINTR:
|
||||
break; /* get out of switch and retry */
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif defined(CONFIG_WIN32)
|
||||
#include <synchapi.h>
|
||||
|
||||
static inline void qemu_futex_wake_all(void *f)
|
||||
{
|
||||
WakeByAddressAll(f);
|
||||
}
|
||||
|
||||
static inline void qemu_futex_wake_single(void *f)
|
||||
{
|
||||
WakeByAddressSingle(f);
|
||||
}
|
||||
|
||||
static inline void qemu_futex_wait(void *f, unsigned val)
|
||||
{
|
||||
WaitOnAddress(f, &val, sizeof(val), INFINITE);
|
||||
}
|
||||
#else
|
||||
#undef HAVE_FUTEX
|
||||
#endif
|
||||
|
||||
#endif /* QEMU_FUTEX_H */
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* QEMU guest-visible random functions
|
||||
*
|
||||
* Copyright 2019 Linaro, Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_GUEST_RANDOM_H
|
||||
#define QEMU_GUEST_RANDOM_H
|
||||
|
||||
/**
|
||||
* qemu_guest_random_seed_main(const char *seedstr, Error **errp)
|
||||
* @seedstr: a non-NULL pointer to a C string
|
||||
* @errp: an error indicator
|
||||
*
|
||||
* The @seedstr value is that which accompanies the -seed argument.
|
||||
* This forces qemu_guest_getrandom into deterministic mode.
|
||||
*
|
||||
* Returns 0 on success, < 0 on failure while setting *errp.
|
||||
*/
|
||||
int qemu_guest_random_seed_main(const char *seedstr, Error **errp);
|
||||
|
||||
/**
|
||||
* qemu_guest_random_seed_thread_part1(void)
|
||||
*
|
||||
* If qemu_getrandom is in deterministic mode, returns an
|
||||
* independent seed for the new thread. Otherwise returns 0.
|
||||
*/
|
||||
uint64_t qemu_guest_random_seed_thread_part1(void);
|
||||
|
||||
/**
|
||||
* qemu_guest_random_seed_thread_part2(uint64_t seed)
|
||||
* @seed: a value for the new thread.
|
||||
*
|
||||
* If qemu_guest_getrandom is in deterministic mode, this stores an
|
||||
* independent seed for the new thread. Otherwise a no-op.
|
||||
*/
|
||||
void qemu_guest_random_seed_thread_part2(uint64_t seed);
|
||||
|
||||
/**
|
||||
* qemu_guest_getrandom(void *buf, size_t len, Error **errp)
|
||||
* @buf: a buffer of bytes to be written
|
||||
* @len: the number of bytes in @buf
|
||||
* @errp: an error indicator
|
||||
*
|
||||
* Fills len bytes in buf with random data. This should only be used
|
||||
* for data presented to the guest. Host-side crypto services should
|
||||
* use qcrypto_random_bytes.
|
||||
*
|
||||
* Returns 0 on success, < 0 on failure while setting *errp.
|
||||
*/
|
||||
int qemu_guest_getrandom(void *buf, size_t len, Error **errp);
|
||||
|
||||
/**
|
||||
* qemu_guest_getrandom_nofail(void *buf, size_t len)
|
||||
* @buf: a buffer of bytes to be written
|
||||
* @len: the number of bytes in @buf
|
||||
*
|
||||
* Like qemu_guest_getrandom, but will assert for failure.
|
||||
* Use this when there is no reasonable recovery.
|
||||
*/
|
||||
void qemu_guest_getrandom_nofail(void *buf, size_t len);
|
||||
|
||||
#endif /* QEMU_GUEST_RANDOM_H */
|
||||
@@ -0,0 +1,353 @@
|
||||
/*
|
||||
* Hierarchical Bitmap Data Type
|
||||
*
|
||||
* Copyright Red Hat, Inc., 2012
|
||||
*
|
||||
* Author: Paolo Bonzini <[email protected]>
|
||||
*
|
||||
* 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 HBITMAP_H
|
||||
#define HBITMAP_H
|
||||
|
||||
#include "bitops.h"
|
||||
#include "host-utils.h"
|
||||
|
||||
typedef struct HBitmap HBitmap;
|
||||
typedef struct HBitmapIter HBitmapIter;
|
||||
|
||||
#define BITS_PER_LEVEL (BITS_PER_LONG == 32 ? 5 : 6)
|
||||
|
||||
/* For 32-bit, the largest that fits in a 4 GiB address space.
|
||||
* For 64-bit, the number of sectors in 1 PiB. Good luck, in
|
||||
* either case... :)
|
||||
*/
|
||||
#define HBITMAP_LOG_MAX_SIZE (BITS_PER_LONG == 32 ? 34 : 41)
|
||||
|
||||
/* We need to place a sentinel in level 0 to speed up iteration. Thus,
|
||||
* we do this instead of HBITMAP_LOG_MAX_SIZE / BITS_PER_LEVEL. The
|
||||
* difference is that it allocates an extra level when HBITMAP_LOG_MAX_SIZE
|
||||
* is an exact multiple of BITS_PER_LEVEL.
|
||||
*/
|
||||
#define HBITMAP_LEVELS ((HBITMAP_LOG_MAX_SIZE / BITS_PER_LEVEL) + 1)
|
||||
|
||||
struct HBitmapIter {
|
||||
const HBitmap *hb;
|
||||
|
||||
/* Copied from hb for access in the inline functions (hb is opaque). */
|
||||
int granularity;
|
||||
|
||||
/* Entry offset into the last-level array of longs. */
|
||||
size_t pos;
|
||||
|
||||
/* The currently-active path in the tree. Each item of cur[i] stores
|
||||
* the bits (i.e. the subtrees) yet to be processed under that node.
|
||||
*/
|
||||
unsigned long cur[HBITMAP_LEVELS];
|
||||
};
|
||||
|
||||
/**
|
||||
* hbitmap_alloc:
|
||||
* @size: Number of bits in the bitmap.
|
||||
* @granularity: Granularity of the bitmap. Aligned groups of 2^@granularity
|
||||
* bits will be represented by a single bit. Each operation on a
|
||||
* range of bits first rounds the bits to determine which group they land
|
||||
* in, and then affect the entire set; iteration will only visit the first
|
||||
* bit of each group.
|
||||
*
|
||||
* Allocate a new HBitmap.
|
||||
*/
|
||||
HBitmap *hbitmap_alloc(uint64_t size, int granularity);
|
||||
|
||||
/**
|
||||
* hbitmap_truncate:
|
||||
* @hb: The bitmap to change the size of.
|
||||
* @size: The number of elements to change the bitmap to accommodate.
|
||||
*
|
||||
* truncate or grow an existing bitmap to accommodate a new number of elements.
|
||||
* This may invalidate existing HBitmapIterators.
|
||||
*/
|
||||
void hbitmap_truncate(HBitmap *hb, uint64_t size);
|
||||
|
||||
/**
|
||||
* hbitmap_merge:
|
||||
*
|
||||
* Store result of merging @a and @b into @result.
|
||||
* @result is allowed to be equal to @a or @b.
|
||||
* All bitmaps must have same size.
|
||||
*/
|
||||
void hbitmap_merge(const HBitmap *a, const HBitmap *b, HBitmap *result);
|
||||
|
||||
/**
|
||||
* hbitmap_empty:
|
||||
* @hb: HBitmap to operate on.
|
||||
*
|
||||
* Return whether the bitmap is empty.
|
||||
*/
|
||||
bool hbitmap_empty(const HBitmap *hb);
|
||||
|
||||
/**
|
||||
* hbitmap_granularity:
|
||||
* @hb: HBitmap to operate on.
|
||||
*
|
||||
* Return the granularity of the HBitmap.
|
||||
*/
|
||||
int hbitmap_granularity(const HBitmap *hb);
|
||||
|
||||
/**
|
||||
* hbitmap_count:
|
||||
* @hb: HBitmap to operate on.
|
||||
*
|
||||
* Return the number of bits set in the HBitmap.
|
||||
*/
|
||||
uint64_t hbitmap_count(const HBitmap *hb);
|
||||
|
||||
/**
|
||||
* hbitmap_set:
|
||||
* @hb: HBitmap to operate on.
|
||||
* @start: First bit to set (0-based).
|
||||
* @count: Number of bits to set.
|
||||
*
|
||||
* Set a consecutive range of bits in an HBitmap.
|
||||
*/
|
||||
void hbitmap_set(HBitmap *hb, uint64_t start, uint64_t count);
|
||||
|
||||
/**
|
||||
* hbitmap_reset:
|
||||
* @hb: HBitmap to operate on.
|
||||
* @start: First bit to reset (0-based).
|
||||
* @count: Number of bits to reset.
|
||||
*
|
||||
* Reset a consecutive range of bits in an HBitmap.
|
||||
* @start and @count must be aligned to bitmap granularity. The only exception
|
||||
* is resetting the tail of the bitmap: @count may be equal to hb->orig_size -
|
||||
* @start, in this case @count may be not aligned. The sum of @start + @count is
|
||||
* allowed to be greater than hb->orig_size, but only if @start < hb->orig_size
|
||||
* and @start + @count = ALIGN_UP(hb->orig_size, granularity).
|
||||
*/
|
||||
void hbitmap_reset(HBitmap *hb, uint64_t start, uint64_t count);
|
||||
|
||||
/**
|
||||
* hbitmap_reset_all:
|
||||
* @hb: HBitmap to operate on.
|
||||
*
|
||||
* Reset all bits in an HBitmap.
|
||||
*/
|
||||
void hbitmap_reset_all(HBitmap *hb);
|
||||
|
||||
/**
|
||||
* hbitmap_get:
|
||||
* @hb: HBitmap to operate on.
|
||||
* @item: Bit to query (0-based).
|
||||
*
|
||||
* Return whether the @item-th bit in an HBitmap is set.
|
||||
*/
|
||||
bool hbitmap_get(const HBitmap *hb, uint64_t item);
|
||||
|
||||
/**
|
||||
* hbitmap_is_serializable:
|
||||
* @hb: HBitmap which should be (de-)serialized.
|
||||
*
|
||||
* Returns whether the bitmap can actually be (de-)serialized. Other
|
||||
* (de-)serialization functions may only be invoked if this function returns
|
||||
* true.
|
||||
*
|
||||
* Calling (de-)serialization functions does not affect a bitmap's
|
||||
* (de-)serializability.
|
||||
*/
|
||||
bool hbitmap_is_serializable(const HBitmap *hb);
|
||||
|
||||
/**
|
||||
* hbitmap_serialization_align:
|
||||
* @hb: HBitmap to operate on.
|
||||
*
|
||||
* Required alignment of serialization chunks, used by other serialization
|
||||
* functions. For every chunk:
|
||||
* 1. Chunk start should be aligned to this granularity.
|
||||
* 2. Chunk size should be aligned too, except for last chunk (for which
|
||||
* start + count == hb->size)
|
||||
*/
|
||||
uint64_t hbitmap_serialization_align(const HBitmap *hb);
|
||||
|
||||
/**
|
||||
* hbitmap_serialization_size:
|
||||
* @hb: HBitmap to operate on.
|
||||
* @start: Starting bit
|
||||
* @count: Number of bits
|
||||
*
|
||||
* Return number of bytes hbitmap_(de)serialize_part needs
|
||||
*/
|
||||
uint64_t hbitmap_serialization_size(const HBitmap *hb,
|
||||
uint64_t start, uint64_t count);
|
||||
|
||||
/**
|
||||
* hbitmap_serialize_part
|
||||
* @hb: HBitmap to operate on.
|
||||
* @buf: Buffer to store serialized bitmap.
|
||||
* @start: First bit to store.
|
||||
* @count: Number of bits to store.
|
||||
*
|
||||
* Stores HBitmap data corresponding to given region. The format of saved data
|
||||
* is linear sequence of bits, so it can be used by hbitmap_deserialize_part
|
||||
* independently of endianness and size of HBitmap level array elements
|
||||
*/
|
||||
void hbitmap_serialize_part(const HBitmap *hb, uint8_t *buf,
|
||||
uint64_t start, uint64_t count);
|
||||
|
||||
/**
|
||||
* hbitmap_deserialize_part
|
||||
* @hb: HBitmap to operate on.
|
||||
* @buf: Buffer to restore bitmap data from.
|
||||
* @start: First bit to restore.
|
||||
* @count: Number of bits to restore.
|
||||
* @finish: Whether to call hbitmap_deserialize_finish automatically.
|
||||
*
|
||||
* Restores HBitmap data corresponding to given region. The format is the same
|
||||
* as for hbitmap_serialize_part.
|
||||
*
|
||||
* If @finish is false, caller must call hbitmap_serialize_finish before using
|
||||
* the bitmap.
|
||||
*/
|
||||
void hbitmap_deserialize_part(HBitmap *hb, uint8_t *buf,
|
||||
uint64_t start, uint64_t count,
|
||||
bool finish);
|
||||
|
||||
/**
|
||||
* hbitmap_deserialize_zeroes
|
||||
* @hb: HBitmap to operate on.
|
||||
* @start: First bit to restore.
|
||||
* @count: Number of bits to restore.
|
||||
* @finish: Whether to call hbitmap_deserialize_finish automatically.
|
||||
*
|
||||
* Fills the bitmap with zeroes.
|
||||
*
|
||||
* If @finish is false, caller must call hbitmap_serialize_finish before using
|
||||
* the bitmap.
|
||||
*/
|
||||
void hbitmap_deserialize_zeroes(HBitmap *hb, uint64_t start, uint64_t count,
|
||||
bool finish);
|
||||
|
||||
/**
|
||||
* hbitmap_deserialize_ones
|
||||
* @hb: HBitmap to operate on.
|
||||
* @start: First bit to restore.
|
||||
* @count: Number of bits to restore.
|
||||
* @finish: Whether to call hbitmap_deserialize_finish automatically.
|
||||
*
|
||||
* Fills the bitmap with ones.
|
||||
*
|
||||
* If @finish is false, caller must call hbitmap_serialize_finish before using
|
||||
* the bitmap.
|
||||
*/
|
||||
void hbitmap_deserialize_ones(HBitmap *hb, uint64_t start, uint64_t count,
|
||||
bool finish);
|
||||
|
||||
/**
|
||||
* hbitmap_deserialize_finish
|
||||
* @hb: HBitmap to operate on.
|
||||
*
|
||||
* Repair HBitmap after calling hbitmap_deserialize_data. Actually, all HBitmap
|
||||
* layers are restored here.
|
||||
*/
|
||||
void hbitmap_deserialize_finish(HBitmap *hb);
|
||||
|
||||
/**
|
||||
* hbitmap_sha256:
|
||||
* @bitmap: HBitmap to operate on.
|
||||
*
|
||||
* Returns SHA256 hash of the last level.
|
||||
*/
|
||||
char *hbitmap_sha256(const HBitmap *bitmap, Error **errp);
|
||||
|
||||
/**
|
||||
* hbitmap_free:
|
||||
* @hb: HBitmap to operate on.
|
||||
*
|
||||
* Free an HBitmap and all of its associated memory.
|
||||
*/
|
||||
void hbitmap_free(HBitmap *hb);
|
||||
|
||||
/**
|
||||
* hbitmap_iter_init:
|
||||
* @hbi: HBitmapIter to initialize.
|
||||
* @hb: HBitmap to iterate on.
|
||||
* @first: First bit to visit (0-based, must be strictly less than the
|
||||
* size of the bitmap).
|
||||
*
|
||||
* Set up @hbi to iterate on the HBitmap @hb. hbitmap_iter_next will return
|
||||
* the lowest-numbered bit that is set in @hb, starting at @first.
|
||||
*
|
||||
* Concurrent setting of bits is acceptable, and will at worst cause the
|
||||
* iteration to miss some of those bits.
|
||||
*
|
||||
* The concurrent resetting of bits is OK.
|
||||
*/
|
||||
void hbitmap_iter_init(HBitmapIter *hbi, const HBitmap *hb, uint64_t first);
|
||||
|
||||
/*
|
||||
* hbitmap_next_dirty:
|
||||
*
|
||||
* Find next dirty bit within selected range. If not found, return -1.
|
||||
*
|
||||
* @hb: The HBitmap to operate on
|
||||
* @start: The bit to start from.
|
||||
* @count: Number of bits to proceed. If @start+@count > bitmap size, the whole
|
||||
* bitmap is looked through. You can use INT64_MAX as @count to search up to
|
||||
* the bitmap end.
|
||||
*/
|
||||
int64_t hbitmap_next_dirty(const HBitmap *hb, int64_t start, int64_t count);
|
||||
|
||||
/* hbitmap_next_zero:
|
||||
*
|
||||
* Find next not dirty bit within selected range. If not found, return -1.
|
||||
*
|
||||
* @hb: The HBitmap to operate on
|
||||
* @start: The bit to start from.
|
||||
* @count: Number of bits to proceed. If @start+@count > bitmap size, the whole
|
||||
* bitmap is looked through. You can use INT64_MAX as @count to search up to
|
||||
* the bitmap end.
|
||||
*/
|
||||
int64_t hbitmap_next_zero(const HBitmap *hb, int64_t start, int64_t count);
|
||||
|
||||
/* hbitmap_next_dirty_area:
|
||||
* @hb: The HBitmap to operate on
|
||||
* @start: the offset to start from
|
||||
* @end: end of requested area
|
||||
* @max_dirty_count: limit for out parameter dirty_count
|
||||
* @dirty_start: on success: start of found area
|
||||
* @dirty_count: on success: length of found area
|
||||
*
|
||||
* If dirty area found within [@start, @end), returns true and sets
|
||||
* @dirty_start and @dirty_count appropriately. @dirty_count will not exceed
|
||||
* @max_dirty_count.
|
||||
* If dirty area was not found, returns false and leaves @dirty_start and
|
||||
* @dirty_count unchanged.
|
||||
*/
|
||||
bool hbitmap_next_dirty_area(const HBitmap *hb, int64_t start, int64_t end,
|
||||
int64_t max_dirty_count,
|
||||
int64_t *dirty_start, int64_t *dirty_count);
|
||||
|
||||
/*
|
||||
* hbitmap_status:
|
||||
* @hb: The HBitmap to operate on
|
||||
* @start: The bit to start from
|
||||
* @count: Number of bits to proceed
|
||||
* @pnum: Out-parameter. How many bits has same value starting from @start
|
||||
*
|
||||
* Returns true if bitmap is dirty at @start, false otherwise.
|
||||
*/
|
||||
bool hbitmap_status(const HBitmap *hb, int64_t start, int64_t count,
|
||||
int64_t *pnum);
|
||||
|
||||
/**
|
||||
* hbitmap_iter_next:
|
||||
* @hbi: HBitmapIter to operate on.
|
||||
*
|
||||
* Return the next bit that is set in @hbi's associated HBitmap,
|
||||
* or -1 if all remaining bits are zero.
|
||||
*/
|
||||
int64_t hbitmap_iter_next(HBitmapIter *hbi);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,13 @@
|
||||
#ifndef QEMU_HELP_TEXTS_H
|
||||
#define QEMU_HELP_TEXTS_H
|
||||
|
||||
/* Copyright string for -version arguments, About dialogs, etc */
|
||||
#define QEMU_COPYRIGHT "Copyright (c) 2003-2026 " \
|
||||
"Fabrice Bellard and the QEMU Project developers"
|
||||
|
||||
/* Bug reporting information for --help arguments, About dialogs, etc */
|
||||
#define QEMU_HELP_BOTTOM \
|
||||
"See <https://qemu.org/contribute/report-a-bug> for how to report bugs.\n" \
|
||||
"More information on the QEMU project at <https://qemu.org>."
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,33 @@
|
||||
#ifndef QEMU_HELP_OPTION_H
|
||||
#define QEMU_HELP_OPTION_H
|
||||
|
||||
/**
|
||||
* is_help_option:
|
||||
* @s: string to test
|
||||
*
|
||||
* Check whether @s is one of the standard strings which indicate
|
||||
* that the user is asking for a list of the valid values for a
|
||||
* command option like -cpu or -M. The current accepted strings
|
||||
* are 'help' and '?'. '?' is deprecated (it is a shell wildcard
|
||||
* which makes it annoying to use in a reliable way) but provided
|
||||
* for backwards compatibility.
|
||||
*
|
||||
* Returns: true if @s is a request for a list.
|
||||
*/
|
||||
static inline bool is_help_option(const char *s)
|
||||
{
|
||||
return !strcmp(s, "?") || !strcmp(s, "help");
|
||||
}
|
||||
|
||||
static inline int starts_with_help_option(const char *s)
|
||||
{
|
||||
if (*s == '?') {
|
||||
return 1;
|
||||
}
|
||||
if (g_str_has_prefix(s, "help")) {
|
||||
return 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* API for host PCI MMIO accesses (e.g. Linux VFIO BARs)
|
||||
*
|
||||
* Copyright 2025 IBM Corp.
|
||||
* Author(s): Farhan Ali <[email protected]>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef HOST_PCI_MMIO_H
|
||||
#define HOST_PCI_MMIO_H
|
||||
|
||||
#include "qemu/bswap.h"
|
||||
#include "qemu/s390x_pci_mmio.h"
|
||||
|
||||
static inline uint8_t host_pci_ldub_p(const void *ioaddr)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
#ifdef __s390x__
|
||||
ret = s390x_pci_mmio_read_8(ioaddr);
|
||||
#else
|
||||
ret = ldub_p(ioaddr);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline uint16_t host_pci_lduw_le_p(const void *ioaddr)
|
||||
{
|
||||
uint16_t ret = 0;
|
||||
#ifdef __s390x__
|
||||
ret = le16_to_cpu(s390x_pci_mmio_read_16(ioaddr));
|
||||
#else
|
||||
ret = lduw_le_p(ioaddr);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline uint32_t host_pci_ldl_le_p(const void *ioaddr)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
#ifdef __s390x__
|
||||
ret = le32_to_cpu(s390x_pci_mmio_read_32(ioaddr));
|
||||
#else
|
||||
ret = ldl_le_p(ioaddr);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline uint64_t host_pci_ldq_le_p(const void *ioaddr)
|
||||
{
|
||||
uint64_t ret = 0;
|
||||
#ifdef __s390x__
|
||||
ret = le64_to_cpu(s390x_pci_mmio_read_64(ioaddr));
|
||||
#else
|
||||
ret = ldq_le_p(ioaddr);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void host_pci_stb_p(void *ioaddr, uint8_t val)
|
||||
{
|
||||
#ifdef __s390x__
|
||||
s390x_pci_mmio_write_8(ioaddr, val);
|
||||
#else
|
||||
stb_p(ioaddr, val);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void host_pci_stw_le_p(void *ioaddr, uint16_t val)
|
||||
{
|
||||
#ifdef __s390x__
|
||||
s390x_pci_mmio_write_16(ioaddr, cpu_to_le16(val));
|
||||
#else
|
||||
stw_le_p(ioaddr, val);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void host_pci_stl_le_p(void *ioaddr, uint32_t val)
|
||||
{
|
||||
#ifdef __s390x__
|
||||
s390x_pci_mmio_write_32(ioaddr, cpu_to_le32(val));
|
||||
#else
|
||||
stl_le_p(ioaddr, val);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void host_pci_stq_le_p(void *ioaddr, uint64_t val)
|
||||
{
|
||||
#ifdef __s390x__
|
||||
s390x_pci_mmio_write_64(ioaddr, cpu_to_le64(val));
|
||||
#else
|
||||
stq_le_p(ioaddr, val);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline uint64_t host_pci_ldn_le_p(const void *ioaddr, int sz)
|
||||
{
|
||||
switch (sz) {
|
||||
case 1:
|
||||
return host_pci_ldub_p(ioaddr);
|
||||
case 2:
|
||||
return host_pci_lduw_le_p(ioaddr);
|
||||
case 4:
|
||||
return host_pci_ldl_le_p(ioaddr);
|
||||
case 8:
|
||||
return host_pci_ldq_le_p(ioaddr);
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void host_pci_stn_le_p(void *ioaddr, int sz, uint64_t v)
|
||||
{
|
||||
switch (sz) {
|
||||
case 1:
|
||||
host_pci_stb_p(ioaddr, v);
|
||||
break;
|
||||
case 2:
|
||||
host_pci_stw_le_p(ioaddr, v);
|
||||
break;
|
||||
case 4:
|
||||
host_pci_stl_le_p(ioaddr, v);
|
||||
break;
|
||||
case 8:
|
||||
host_pci_stq_le_p(ioaddr, v);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,929 @@
|
||||
/*
|
||||
* Utility compute operations used by translated code.
|
||||
*
|
||||
* Copyright (c) 2007 Thiemo Seufer
|
||||
* Copyright (c) 2007 Jocelyn Mayer
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Portions of this work are licensed under the terms of the GNU GPL,
|
||||
* version 2 or later. See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef HOST_UTILS_H
|
||||
#define HOST_UTILS_H
|
||||
|
||||
#include "qemu/int128.h"
|
||||
|
||||
#ifdef CONFIG_INT128
|
||||
static inline void mulu64(uint64_t *plow, uint64_t *phigh,
|
||||
uint64_t a, uint64_t b)
|
||||
{
|
||||
__uint128_t r = (__uint128_t)a * b;
|
||||
*plow = r;
|
||||
*phigh = r >> 64;
|
||||
}
|
||||
|
||||
static inline void muls64(uint64_t *plow, uint64_t *phigh,
|
||||
int64_t a, int64_t b)
|
||||
{
|
||||
__int128_t r = (__int128_t)a * b;
|
||||
*plow = r;
|
||||
*phigh = r >> 64;
|
||||
}
|
||||
|
||||
/* compute with 96 bit intermediate result: (a*b)/c */
|
||||
static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
|
||||
{
|
||||
return (__int128_t)a * b / c;
|
||||
}
|
||||
|
||||
static inline uint64_t muldiv64_round_up(uint64_t a, uint32_t b, uint32_t c)
|
||||
{
|
||||
return ((__int128_t)a * b + c - 1) / c;
|
||||
}
|
||||
|
||||
static inline uint64_t divu128(uint64_t *plow, uint64_t *phigh,
|
||||
uint64_t divisor)
|
||||
{
|
||||
__uint128_t dividend = ((__uint128_t)*phigh << 64) | *plow;
|
||||
__uint128_t result = dividend / divisor;
|
||||
|
||||
*plow = result;
|
||||
*phigh = result >> 64;
|
||||
return dividend % divisor;
|
||||
}
|
||||
|
||||
static inline int64_t divs128(uint64_t *plow, int64_t *phigh,
|
||||
int64_t divisor)
|
||||
{
|
||||
__int128_t dividend = ((__int128_t)*phigh << 64) | *plow;
|
||||
__int128_t result = dividend / divisor;
|
||||
|
||||
*plow = result;
|
||||
*phigh = result >> 64;
|
||||
return dividend % divisor;
|
||||
}
|
||||
#else
|
||||
void muls64(uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b);
|
||||
void mulu64(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b);
|
||||
uint64_t divu128(uint64_t *plow, uint64_t *phigh, uint64_t divisor);
|
||||
int64_t divs128(uint64_t *plow, int64_t *phigh, int64_t divisor);
|
||||
|
||||
static inline uint64_t muldiv64_rounding(uint64_t a, uint32_t b, uint32_t c,
|
||||
bool round_up)
|
||||
{
|
||||
union {
|
||||
uint64_t ll;
|
||||
struct {
|
||||
#if HOST_BIG_ENDIAN
|
||||
uint32_t high, low;
|
||||
#else
|
||||
uint32_t low, high;
|
||||
#endif
|
||||
} l;
|
||||
} u, res;
|
||||
uint64_t rl, rh;
|
||||
|
||||
u.ll = a;
|
||||
rl = (uint64_t)u.l.low * (uint64_t)b;
|
||||
if (round_up) {
|
||||
rl += c - 1;
|
||||
}
|
||||
rh = (uint64_t)u.l.high * (uint64_t)b;
|
||||
rh += (rl >> 32);
|
||||
res.l.high = rh / c;
|
||||
res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
|
||||
return res.ll;
|
||||
}
|
||||
|
||||
static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
|
||||
{
|
||||
return muldiv64_rounding(a, b, c, false);
|
||||
}
|
||||
|
||||
static inline uint64_t muldiv64_round_up(uint64_t a, uint32_t b, uint32_t c)
|
||||
{
|
||||
return muldiv64_rounding(a, b, c, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* clz8 - count leading zeros in a 8-bit value.
|
||||
* @val: The value to search
|
||||
*
|
||||
* Returns 8 if the value is zero. Note that the GCC builtin is
|
||||
* undefined if the value is zero.
|
||||
*
|
||||
* Note that the GCC builtin will upcast its argument to an `unsigned int`
|
||||
* so this function subtracts off the number of prepended zeroes.
|
||||
*/
|
||||
static inline int clz8(uint8_t val)
|
||||
{
|
||||
return val ? __builtin_clz(val) - 24 : 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* clz16 - count leading zeros in a 16-bit value.
|
||||
* @val: The value to search
|
||||
*
|
||||
* Returns 16 if the value is zero. Note that the GCC builtin is
|
||||
* undefined if the value is zero.
|
||||
*
|
||||
* Note that the GCC builtin will upcast its argument to an `unsigned int`
|
||||
* so this function subtracts off the number of prepended zeroes.
|
||||
*/
|
||||
static inline int clz16(uint16_t val)
|
||||
{
|
||||
return val ? __builtin_clz(val) - 16 : 16;
|
||||
}
|
||||
|
||||
/**
|
||||
* clz32 - count leading zeros in a 32-bit value.
|
||||
* @val: The value to search
|
||||
*
|
||||
* Returns 32 if the value is zero. Note that the GCC builtin is
|
||||
* undefined if the value is zero.
|
||||
*/
|
||||
static inline int clz32(uint32_t val)
|
||||
{
|
||||
return val ? __builtin_clz(val) : 32;
|
||||
}
|
||||
|
||||
/**
|
||||
* clo32 - count leading ones in a 32-bit value.
|
||||
* @val: The value to search
|
||||
*
|
||||
* Returns 32 if the value is -1.
|
||||
*/
|
||||
static inline int clo32(uint32_t val)
|
||||
{
|
||||
return clz32(~val);
|
||||
}
|
||||
|
||||
/**
|
||||
* clz64 - count leading zeros in a 64-bit value.
|
||||
* @val: The value to search
|
||||
*
|
||||
* Returns 64 if the value is zero. Note that the GCC builtin is
|
||||
* undefined if the value is zero.
|
||||
*/
|
||||
static inline int clz64(uint64_t val)
|
||||
{
|
||||
return val ? __builtin_clzll(val) : 64;
|
||||
}
|
||||
|
||||
/**
|
||||
* clo64 - count leading ones in a 64-bit value.
|
||||
* @val: The value to search
|
||||
*
|
||||
* Returns 64 if the value is -1.
|
||||
*/
|
||||
static inline int clo64(uint64_t val)
|
||||
{
|
||||
return clz64(~val);
|
||||
}
|
||||
|
||||
/**
|
||||
* ctz8 - count trailing zeros in a 8-bit value.
|
||||
* @val: The value to search
|
||||
*
|
||||
* Returns 8 if the value is zero. Note that the GCC builtin is
|
||||
* undefined if the value is zero.
|
||||
*/
|
||||
static inline int ctz8(uint8_t val)
|
||||
{
|
||||
return val ? __builtin_ctz(val) : 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* ctz16 - count trailing zeros in a 16-bit value.
|
||||
* @val: The value to search
|
||||
*
|
||||
* Returns 16 if the value is zero. Note that the GCC builtin is
|
||||
* undefined if the value is zero.
|
||||
*/
|
||||
static inline int ctz16(uint16_t val)
|
||||
{
|
||||
return val ? __builtin_ctz(val) : 16;
|
||||
}
|
||||
|
||||
/**
|
||||
* ctz32 - count trailing zeros in a 32-bit value.
|
||||
* @val: The value to search
|
||||
*
|
||||
* Returns 32 if the value is zero. Note that the GCC builtin is
|
||||
* undefined if the value is zero.
|
||||
*/
|
||||
static inline int ctz32(uint32_t val)
|
||||
{
|
||||
return val ? __builtin_ctz(val) : 32;
|
||||
}
|
||||
|
||||
/**
|
||||
* cto32 - count trailing ones in a 32-bit value.
|
||||
* @val: The value to search
|
||||
*
|
||||
* Returns 32 if the value is -1.
|
||||
*/
|
||||
static inline int cto32(uint32_t val)
|
||||
{
|
||||
return ctz32(~val);
|
||||
}
|
||||
|
||||
/**
|
||||
* ctz64 - count trailing zeros in a 64-bit value.
|
||||
* @val: The value to search
|
||||
*
|
||||
* Returns 64 if the value is zero. Note that the GCC builtin is
|
||||
* undefined if the value is zero.
|
||||
*/
|
||||
static inline int ctz64(uint64_t val)
|
||||
{
|
||||
return val ? __builtin_ctzll(val) : 64;
|
||||
}
|
||||
|
||||
/**
|
||||
* cto64 - count trailing ones in a 64-bit value.
|
||||
* @val: The value to search
|
||||
*
|
||||
* Returns 64 if the value is -1.
|
||||
*/
|
||||
static inline int cto64(uint64_t val)
|
||||
{
|
||||
return ctz64(~val);
|
||||
}
|
||||
|
||||
/**
|
||||
* clrsb32 - count leading redundant sign bits in a 32-bit value.
|
||||
* @val: The value to search
|
||||
*
|
||||
* Returns the number of bits following the sign bit that are equal to it.
|
||||
* No special cases; output range is [0-31].
|
||||
*/
|
||||
static inline int clrsb32(uint32_t val)
|
||||
{
|
||||
#if __has_builtin(__builtin_clrsb) || !defined(__clang__)
|
||||
return __builtin_clrsb(val);
|
||||
#else
|
||||
return clz32(val ^ ((int32_t)val >> 1)) - 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* clrsb64 - count leading redundant sign bits in a 64-bit value.
|
||||
* @val: The value to search
|
||||
*
|
||||
* Returns the number of bits following the sign bit that are equal to it.
|
||||
* No special cases; output range is [0-63].
|
||||
*/
|
||||
static inline int clrsb64(uint64_t val)
|
||||
{
|
||||
#if __has_builtin(__builtin_clrsbll) || !defined(__clang__)
|
||||
return __builtin_clrsbll(val);
|
||||
#else
|
||||
return clz64(val ^ ((int64_t)val >> 1)) - 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* ctpop8 - count the population of one bits in an 8-bit value.
|
||||
* @val: The value to search
|
||||
*/
|
||||
static inline int ctpop8(uint8_t val)
|
||||
{
|
||||
return __builtin_popcount(val);
|
||||
}
|
||||
|
||||
/*
|
||||
* parity8 - return the parity (1 = odd) of an 8-bit value.
|
||||
* @val: The value to search
|
||||
*/
|
||||
static inline int parity8(uint8_t val)
|
||||
{
|
||||
return __builtin_parity(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* ctpop16 - count the population of one bits in a 16-bit value.
|
||||
* @val: The value to search
|
||||
*/
|
||||
static inline int ctpop16(uint16_t val)
|
||||
{
|
||||
return __builtin_popcount(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* ctpop32 - count the population of one bits in a 32-bit value.
|
||||
* @val: The value to search
|
||||
*/
|
||||
static inline int ctpop32(uint32_t val)
|
||||
{
|
||||
return __builtin_popcount(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* ctpop64 - count the population of one bits in a 64-bit value.
|
||||
* @val: The value to search
|
||||
*/
|
||||
static inline int ctpop64(uint64_t val)
|
||||
{
|
||||
return __builtin_popcountll(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* revbit8 - reverse the bits in an 8-bit value.
|
||||
* @x: The value to modify.
|
||||
*/
|
||||
static inline uint8_t revbit8(uint8_t x)
|
||||
{
|
||||
#if __has_builtin(__builtin_bitreverse8)
|
||||
return __builtin_bitreverse8(x);
|
||||
#else
|
||||
/* Assign the correct nibble position. */
|
||||
x = ((x & 0xf0) >> 4)
|
||||
| ((x & 0x0f) << 4);
|
||||
/* Assign the correct bit position. */
|
||||
x = ((x & 0x88) >> 3)
|
||||
| ((x & 0x44) >> 1)
|
||||
| ((x & 0x22) << 1)
|
||||
| ((x & 0x11) << 3);
|
||||
return x;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* revbit16 - reverse the bits in a 16-bit value.
|
||||
* @x: The value to modify.
|
||||
*/
|
||||
static inline uint16_t revbit16(uint16_t x)
|
||||
{
|
||||
#if __has_builtin(__builtin_bitreverse16)
|
||||
return __builtin_bitreverse16(x);
|
||||
#else
|
||||
/* Assign the correct byte position. */
|
||||
x = __builtin_bswap16(x);
|
||||
/* Assign the correct nibble position. */
|
||||
x = ((x & 0xf0f0) >> 4)
|
||||
| ((x & 0x0f0f) << 4);
|
||||
/* Assign the correct bit position. */
|
||||
x = ((x & 0x8888) >> 3)
|
||||
| ((x & 0x4444) >> 1)
|
||||
| ((x & 0x2222) << 1)
|
||||
| ((x & 0x1111) << 3);
|
||||
return x;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* revbit32 - reverse the bits in a 32-bit value.
|
||||
* @x: The value to modify.
|
||||
*/
|
||||
static inline uint32_t revbit32(uint32_t x)
|
||||
{
|
||||
#if __has_builtin(__builtin_bitreverse32)
|
||||
return __builtin_bitreverse32(x);
|
||||
#else
|
||||
/* Assign the correct byte position. */
|
||||
x = __builtin_bswap32(x);
|
||||
/* Assign the correct nibble position. */
|
||||
x = ((x & 0xf0f0f0f0u) >> 4)
|
||||
| ((x & 0x0f0f0f0fu) << 4);
|
||||
/* Assign the correct bit position. */
|
||||
x = ((x & 0x88888888u) >> 3)
|
||||
| ((x & 0x44444444u) >> 1)
|
||||
| ((x & 0x22222222u) << 1)
|
||||
| ((x & 0x11111111u) << 3);
|
||||
return x;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* revbit64 - reverse the bits in a 64-bit value.
|
||||
* @x: The value to modify.
|
||||
*/
|
||||
static inline uint64_t revbit64(uint64_t x)
|
||||
{
|
||||
#if __has_builtin(__builtin_bitreverse64)
|
||||
return __builtin_bitreverse64(x);
|
||||
#else
|
||||
/* Assign the correct byte position. */
|
||||
x = __builtin_bswap64(x);
|
||||
/* Assign the correct nibble position. */
|
||||
x = ((x & 0xf0f0f0f0f0f0f0f0ull) >> 4)
|
||||
| ((x & 0x0f0f0f0f0f0f0f0full) << 4);
|
||||
/* Assign the correct bit position. */
|
||||
x = ((x & 0x8888888888888888ull) >> 3)
|
||||
| ((x & 0x4444444444444444ull) >> 1)
|
||||
| ((x & 0x2222222222222222ull) << 1)
|
||||
| ((x & 0x1111111111111111ull) << 3);
|
||||
return x;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the absolute value of a 64-bit integer as an unsigned 64-bit value
|
||||
*/
|
||||
static inline uint64_t uabs64(int64_t v)
|
||||
{
|
||||
return v < 0 ? -v : v;
|
||||
}
|
||||
|
||||
/**
|
||||
* sadd32_overflow - addition with overflow indication
|
||||
* @x, @y: addends
|
||||
* @ret: Output for sum
|
||||
*
|
||||
* Computes *@ret = @x + @y, and returns true if and only if that
|
||||
* value has been truncated.
|
||||
*/
|
||||
static inline bool sadd32_overflow(int32_t x, int32_t y, int32_t *ret)
|
||||
{
|
||||
return __builtin_add_overflow(x, y, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* sadd64_overflow - addition with overflow indication
|
||||
* @x, @y: addends
|
||||
* @ret: Output for sum
|
||||
*
|
||||
* Computes *@ret = @x + @y, and returns true if and only if that
|
||||
* value has been truncated.
|
||||
*/
|
||||
static inline bool sadd64_overflow(int64_t x, int64_t y, int64_t *ret)
|
||||
{
|
||||
return __builtin_add_overflow(x, y, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* uadd32_overflow - addition with overflow indication
|
||||
* @x, @y: addends
|
||||
* @ret: Output for sum
|
||||
*
|
||||
* Computes *@ret = @x + @y, and returns true if and only if that
|
||||
* value has been truncated.
|
||||
*/
|
||||
static inline bool uadd32_overflow(uint32_t x, uint32_t y, uint32_t *ret)
|
||||
{
|
||||
return __builtin_add_overflow(x, y, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* uadd64_overflow - addition with overflow indication
|
||||
* @x, @y: addends
|
||||
* @ret: Output for sum
|
||||
*
|
||||
* Computes *@ret = @x + @y, and returns true if and only if that
|
||||
* value has been truncated.
|
||||
*/
|
||||
static inline bool uadd64_overflow(uint64_t x, uint64_t y, uint64_t *ret)
|
||||
{
|
||||
return __builtin_add_overflow(x, y, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* ssub32_overflow - subtraction with overflow indication
|
||||
* @x: Minuend
|
||||
* @y: Subtrahend
|
||||
* @ret: Output for difference
|
||||
*
|
||||
* Computes *@ret = @x - @y, and returns true if and only if that
|
||||
* value has been truncated.
|
||||
*/
|
||||
static inline bool ssub32_overflow(int32_t x, int32_t y, int32_t *ret)
|
||||
{
|
||||
return __builtin_sub_overflow(x, y, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* ssub64_overflow - subtraction with overflow indication
|
||||
* @x: Minuend
|
||||
* @y: Subtrahend
|
||||
* @ret: Output for sum
|
||||
*
|
||||
* Computes *@ret = @x - @y, and returns true if and only if that
|
||||
* value has been truncated.
|
||||
*/
|
||||
static inline bool ssub64_overflow(int64_t x, int64_t y, int64_t *ret)
|
||||
{
|
||||
return __builtin_sub_overflow(x, y, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* usub32_overflow - subtraction with overflow indication
|
||||
* @x: Minuend
|
||||
* @y: Subtrahend
|
||||
* @ret: Output for sum
|
||||
*
|
||||
* Computes *@ret = @x - @y, and returns true if and only if that
|
||||
* value has been truncated.
|
||||
*/
|
||||
static inline bool usub32_overflow(uint32_t x, uint32_t y, uint32_t *ret)
|
||||
{
|
||||
return __builtin_sub_overflow(x, y, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* usub64_overflow - subtraction with overflow indication
|
||||
* @x: Minuend
|
||||
* @y: Subtrahend
|
||||
* @ret: Output for sum
|
||||
*
|
||||
* Computes *@ret = @x - @y, and returns true if and only if that
|
||||
* value has been truncated.
|
||||
*/
|
||||
static inline bool usub64_overflow(uint64_t x, uint64_t y, uint64_t *ret)
|
||||
{
|
||||
return __builtin_sub_overflow(x, y, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* smul32_overflow - multiplication with overflow indication
|
||||
* @x, @y: Input multipliers
|
||||
* @ret: Output for product
|
||||
*
|
||||
* Computes *@ret = @x * @y, and returns true if and only if that
|
||||
* value has been truncated.
|
||||
*/
|
||||
static inline bool smul32_overflow(int32_t x, int32_t y, int32_t *ret)
|
||||
{
|
||||
return __builtin_mul_overflow(x, y, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* smul64_overflow - multiplication with overflow indication
|
||||
* @x, @y: Input multipliers
|
||||
* @ret: Output for product
|
||||
*
|
||||
* Computes *@ret = @x * @y, and returns true if and only if that
|
||||
* value has been truncated.
|
||||
*/
|
||||
static inline bool smul64_overflow(int64_t x, int64_t y, int64_t *ret)
|
||||
{
|
||||
return __builtin_mul_overflow(x, y, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* umul32_overflow - multiplication with overflow indication
|
||||
* @x, @y: Input multipliers
|
||||
* @ret: Output for product
|
||||
*
|
||||
* Computes *@ret = @x * @y, and returns true if and only if that
|
||||
* value has been truncated.
|
||||
*/
|
||||
static inline bool umul32_overflow(uint32_t x, uint32_t y, uint32_t *ret)
|
||||
{
|
||||
return __builtin_mul_overflow(x, y, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* umul64_overflow - multiplication with overflow indication
|
||||
* @x, @y: Input multipliers
|
||||
* @ret: Output for product
|
||||
*
|
||||
* Computes *@ret = @x * @y, and returns true if and only if that
|
||||
* value has been truncated.
|
||||
*/
|
||||
static inline bool umul64_overflow(uint64_t x, uint64_t y, uint64_t *ret)
|
||||
{
|
||||
return __builtin_mul_overflow(x, y, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* sadd32_saturate - 32-bit signed addition with saturation
|
||||
* @x, @y: addends
|
||||
*
|
||||
* Computes @x + @y, and saturates rather than truncating the result.
|
||||
*/
|
||||
static inline int32_t sadd32_saturate(int32_t x, int32_t y)
|
||||
{
|
||||
int32_t ret;
|
||||
if (sadd32_overflow(x, y, &ret)) {
|
||||
ret = y < 0 ? INT32_MIN : INT32_MAX;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* sadd64_saturate - 64-bit signed addition with saturation
|
||||
* @x, @y: addends
|
||||
*
|
||||
* Computes @x + @y, and saturates rather than truncating the result.
|
||||
*/
|
||||
static inline int64_t sadd64_saturate(int64_t x, int64_t y)
|
||||
{
|
||||
int64_t ret;
|
||||
if (sadd64_overflow(x, y, &ret)) {
|
||||
ret = y < 0 ? INT64_MIN : INT64_MAX;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* ssub32_saturate - 32-bit signed subtraction with saturation
|
||||
* @x, @y: addends
|
||||
*
|
||||
* Computes @x - @y, and saturates rather than truncating the result.
|
||||
*/
|
||||
static inline int32_t ssub32_saturate(int32_t x, int32_t y)
|
||||
{
|
||||
int32_t ret;
|
||||
if (ssub32_overflow(x, y, &ret)) {
|
||||
ret = x < 0 ? INT32_MIN : INT32_MAX;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* ssub64_saturate - 64-bit signed subtraction with saturation
|
||||
* @x, @y: addends
|
||||
*
|
||||
* Computes @x - @y, and saturates rather than truncating the result.
|
||||
*/
|
||||
static inline int64_t ssub64_saturate(int64_t x, int64_t y)
|
||||
{
|
||||
int64_t ret;
|
||||
if (ssub64_overflow(x, y, &ret)) {
|
||||
ret = x < 0 ? INT64_MIN : INT64_MAX;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unsigned 128x64 multiplication.
|
||||
* Returns true if the result got truncated to 128 bits.
|
||||
* Otherwise, returns false and the multiplication result via plow and phigh.
|
||||
*/
|
||||
static inline bool mulu128(uint64_t *plow, uint64_t *phigh, uint64_t factor)
|
||||
{
|
||||
#if defined(CONFIG_INT128)
|
||||
bool res;
|
||||
__uint128_t r;
|
||||
__uint128_t f = ((__uint128_t)*phigh << 64) | *plow;
|
||||
res = __builtin_mul_overflow(f, factor, &r);
|
||||
|
||||
*plow = r;
|
||||
*phigh = r >> 64;
|
||||
|
||||
return res;
|
||||
#else
|
||||
uint64_t dhi = *phigh;
|
||||
uint64_t dlo = *plow;
|
||||
uint64_t ahi;
|
||||
uint64_t blo, bhi;
|
||||
|
||||
if (dhi == 0) {
|
||||
mulu64(plow, phigh, dlo, factor);
|
||||
return false;
|
||||
}
|
||||
|
||||
mulu64(plow, &ahi, dlo, factor);
|
||||
mulu64(&blo, &bhi, dhi, factor);
|
||||
|
||||
return uadd64_overflow(ahi, blo, phigh) || bhi != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* uadd64_carry - addition with carry-in and carry-out
|
||||
* @x, @y: addends
|
||||
* @pcarry: in-out carry value
|
||||
*
|
||||
* Computes @x + @y + *@pcarry, placing the carry-out back
|
||||
* into *@pcarry and returning the 64-bit sum.
|
||||
*/
|
||||
static inline uint64_t uadd64_carry(uint64_t x, uint64_t y, bool *pcarry)
|
||||
{
|
||||
#if __has_builtin(__builtin_addcll)
|
||||
unsigned long long c = *pcarry;
|
||||
x = __builtin_addcll(x, y, c, &c);
|
||||
*pcarry = c & 1;
|
||||
return x;
|
||||
#else
|
||||
bool c = *pcarry;
|
||||
/* This is clang's internal expansion of __builtin_addc. */
|
||||
c = uadd64_overflow(x, c, &x);
|
||||
c |= uadd64_overflow(x, y, &x);
|
||||
*pcarry = c;
|
||||
return x;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* usub64_borrow - subtraction with borrow-in and borrow-out
|
||||
* @x, @y: addends
|
||||
* @pborrow: in-out borrow value
|
||||
*
|
||||
* Computes @x - @y - *@pborrow, placing the borrow-out back
|
||||
* into *@pborrow and returning the 64-bit sum.
|
||||
*/
|
||||
static inline uint64_t usub64_borrow(uint64_t x, uint64_t y, bool *pborrow)
|
||||
{
|
||||
#if __has_builtin(__builtin_subcll)
|
||||
unsigned long long b = *pborrow;
|
||||
x = __builtin_subcll(x, y, b, &b);
|
||||
*pborrow = b & 1;
|
||||
return x;
|
||||
#else
|
||||
bool b = *pborrow;
|
||||
b = usub64_overflow(x, b, &x);
|
||||
b |= usub64_overflow(x, y, &x);
|
||||
*pborrow = b;
|
||||
return x;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Host type specific sizes of these routines. */
|
||||
|
||||
#if ULONG_MAX == UINT32_MAX
|
||||
# define clzl clz32
|
||||
# define ctzl ctz32
|
||||
# define clol clo32
|
||||
# define ctol cto32
|
||||
# define ctpopl ctpop32
|
||||
# define revbitl revbit32
|
||||
#elif ULONG_MAX == UINT64_MAX
|
||||
# define clzl clz64
|
||||
# define ctzl ctz64
|
||||
# define clol clo64
|
||||
# define ctol cto64
|
||||
# define ctpopl ctpop64
|
||||
# define revbitl revbit64
|
||||
#else
|
||||
# error Unknown sizeof long
|
||||
#endif
|
||||
|
||||
static inline bool is_power_of_2(uint64_t value)
|
||||
{
|
||||
if (!value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !(value & (value - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return @value rounded down to the nearest power of two or zero.
|
||||
*/
|
||||
static inline uint64_t pow2floor(uint64_t value)
|
||||
{
|
||||
if (!value) {
|
||||
/* Avoid undefined shift by 64 */
|
||||
return 0;
|
||||
}
|
||||
return 0x8000000000000000ull >> clz64(value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return @value rounded up to the nearest power of two modulo 2^64.
|
||||
* This is *zero* for @value > 2^63, so be careful.
|
||||
*/
|
||||
static inline uint64_t pow2ceil(uint64_t value)
|
||||
{
|
||||
int n = clz64(value - 1);
|
||||
|
||||
if (!n) {
|
||||
/*
|
||||
* @value - 1 has no leading zeroes, thus @value - 1 >= 2^63
|
||||
* Therefore, either @value == 0 or @value > 2^63.
|
||||
* If it's 0, return 1, else return 0.
|
||||
*/
|
||||
return !value;
|
||||
}
|
||||
return 0x8000000000000000ull >> (n - 1);
|
||||
}
|
||||
|
||||
static inline uint32_t pow2roundup32(uint32_t x)
|
||||
{
|
||||
x |= (x >> 1);
|
||||
x |= (x >> 2);
|
||||
x |= (x >> 4);
|
||||
x |= (x >> 8);
|
||||
x |= (x >> 16);
|
||||
return x + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* urshift - 128-bit Unsigned Right Shift.
|
||||
* @plow: in/out - lower 64-bit integer.
|
||||
* @phigh: in/out - higher 64-bit integer.
|
||||
* @shift: in - bytes to shift, between 0 and 127.
|
||||
*
|
||||
* Result is zero-extended and stored in plow/phigh, which are
|
||||
* input/output variables. Shift values outside the range will
|
||||
* be mod to 128. In other words, the caller is responsible to
|
||||
* verify/assert both the shift range and plow/phigh pointers.
|
||||
*/
|
||||
void urshift(uint64_t *plow, uint64_t *phigh, int32_t shift);
|
||||
|
||||
/**
|
||||
* ulshift - 128-bit Unsigned Left Shift.
|
||||
* @plow: in/out - lower 64-bit integer.
|
||||
* @phigh: in/out - higher 64-bit integer.
|
||||
* @shift: in - bytes to shift, between 0 and 127.
|
||||
* @overflow: out - true if any 1-bit is shifted out.
|
||||
*
|
||||
* Result is zero-extended and stored in plow/phigh, which are
|
||||
* input/output variables. Shift values outside the range will
|
||||
* be mod to 128. In other words, the caller is responsible to
|
||||
* verify/assert both the shift range and plow/phigh pointers.
|
||||
*/
|
||||
void ulshift(uint64_t *plow, uint64_t *phigh, int32_t shift, bool *overflow);
|
||||
|
||||
/* From the GNU Multi Precision Library - longlong.h __udiv_qrnnd
|
||||
* (https://gmplib.org/repo/gmp/file/tip/longlong.h)
|
||||
*
|
||||
* Licensed under the GPLv2/LGPLv3
|
||||
*/
|
||||
static inline uint64_t udiv_qrnnd(uint64_t *r, uint64_t n1,
|
||||
uint64_t n0, uint64_t d)
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
uint64_t q;
|
||||
asm("divq %4" : "=a"(q), "=d"(*r) : "0"(n0), "1"(n1), "rm"(d));
|
||||
return q;
|
||||
#elif defined(__s390x__) && !defined(__clang__)
|
||||
/* Need to use a TImode type to get an even register pair for DLGR. */
|
||||
unsigned __int128 n = (unsigned __int128)n1 << 64 | n0;
|
||||
asm("dlgr %0, %1" : "+r"(n) : "r"(d));
|
||||
*r = n >> 64;
|
||||
return n;
|
||||
#elif defined(_ARCH_PPC64) && defined(_ARCH_PWR7)
|
||||
/* From Power ISA 2.06, programming note for divdeu. */
|
||||
uint64_t q1, q2, Q, r1, r2, R;
|
||||
asm("divdeu %0,%2,%4; divdu %1,%3,%4"
|
||||
: "=&r"(q1), "=r"(q2)
|
||||
: "r"(n1), "r"(n0), "r"(d));
|
||||
r1 = -(q1 * d); /* low part of (n1<<64) - (q1 * d) */
|
||||
r2 = n0 - (q2 * d);
|
||||
Q = q1 + q2;
|
||||
R = r1 + r2;
|
||||
if (R >= d || R < r2) { /* overflow implies R > d */
|
||||
Q += 1;
|
||||
R -= d;
|
||||
}
|
||||
*r = R;
|
||||
return Q;
|
||||
#else
|
||||
uint64_t d0, d1, q0, q1, r1, r0, m;
|
||||
|
||||
d0 = (uint32_t)d;
|
||||
d1 = d >> 32;
|
||||
|
||||
r1 = n1 % d1;
|
||||
q1 = n1 / d1;
|
||||
m = q1 * d0;
|
||||
r1 = (r1 << 32) | (n0 >> 32);
|
||||
if (r1 < m) {
|
||||
q1 -= 1;
|
||||
r1 += d;
|
||||
if (r1 >= d) {
|
||||
if (r1 < m) {
|
||||
q1 -= 1;
|
||||
r1 += d;
|
||||
}
|
||||
}
|
||||
}
|
||||
r1 -= m;
|
||||
|
||||
r0 = r1 % d1;
|
||||
q0 = r1 / d1;
|
||||
m = q0 * d0;
|
||||
r0 = (r0 << 32) | (uint32_t)n0;
|
||||
if (r0 < m) {
|
||||
q0 -= 1;
|
||||
r0 += d;
|
||||
if (r0 >= d) {
|
||||
if (r0 < m) {
|
||||
q0 -= 1;
|
||||
r0 += d;
|
||||
}
|
||||
}
|
||||
}
|
||||
r0 -= m;
|
||||
|
||||
*r = r0;
|
||||
return (q1 << 32) | q0;
|
||||
#endif
|
||||
}
|
||||
|
||||
Int128 divu256(Int128 *plow, Int128 *phigh, Int128 divisor);
|
||||
Int128 divs256(Int128 *plow, Int128 *phigh, Int128 divisor);
|
||||
#endif
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* QEMU "hardware version" constant
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
#ifndef QEMU_HW_VERSION_H
|
||||
#define QEMU_HW_VERSION_H
|
||||
|
||||
/*
|
||||
* Starting on QEMU 2.5, devices with a version string in their
|
||||
* identification data return "2.5+" instead of QEMU_VERSION. Do
|
||||
* NOT change this string as it is visible to guests.
|
||||
*/
|
||||
#define QEMU_HW_VERSION "2.5+"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef QEMU_ID_H
|
||||
#define QEMU_ID_H
|
||||
|
||||
typedef enum IdSubSystems {
|
||||
ID_QDEV,
|
||||
ID_BLOCK,
|
||||
ID_CHR,
|
||||
ID_NET,
|
||||
ID_MAX /* last element, used as array size */
|
||||
} IdSubSystems;
|
||||
|
||||
char *id_generate(IdSubSystems id);
|
||||
bool id_wellformed(const char *id);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,495 @@
|
||||
#ifndef INT128_H
|
||||
#define INT128_H
|
||||
|
||||
/*
|
||||
* With TCI, we need to use libffi for interfacing with TCG helpers.
|
||||
* But libffi does not support __int128_t, and therefore cannot pass
|
||||
* or return values of this type, force use of the Int128 struct.
|
||||
*/
|
||||
#if defined(CONFIG_INT128) && !defined(CONFIG_TCG_INTERPRETER)
|
||||
typedef __int128_t Int128;
|
||||
typedef __int128_t __attribute__((aligned(16))) Int128Aligned;
|
||||
|
||||
static inline Int128 int128_make64(uint64_t a)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
static inline Int128 int128_makes64(int64_t a)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
static inline Int128 int128_make128(uint64_t lo, uint64_t hi)
|
||||
{
|
||||
return (__uint128_t)hi << 64 | lo;
|
||||
}
|
||||
|
||||
static inline uint64_t int128_get64(Int128 a)
|
||||
{
|
||||
uint64_t r = a;
|
||||
assert(r == a);
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline uint64_t int128_getlo(Int128 a)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
static inline int64_t int128_gethi(Int128 a)
|
||||
{
|
||||
return a >> 64;
|
||||
}
|
||||
|
||||
static inline Int128 int128_zero(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline Int128 int128_one(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline Int128 int128_2_64(void)
|
||||
{
|
||||
return (Int128)1 << 64;
|
||||
}
|
||||
|
||||
static inline Int128 int128_exts64(int64_t a)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
static inline Int128 int128_not(Int128 a)
|
||||
{
|
||||
return ~a;
|
||||
}
|
||||
|
||||
static inline Int128 int128_and(Int128 a, Int128 b)
|
||||
{
|
||||
return a & b;
|
||||
}
|
||||
|
||||
static inline Int128 int128_or(Int128 a, Int128 b)
|
||||
{
|
||||
return a | b;
|
||||
}
|
||||
|
||||
static inline Int128 int128_xor(Int128 a, Int128 b)
|
||||
{
|
||||
return a ^ b;
|
||||
}
|
||||
|
||||
static inline Int128 int128_rshift(Int128 a, int n)
|
||||
{
|
||||
return a >> n;
|
||||
}
|
||||
|
||||
static inline Int128 int128_urshift(Int128 a, int n)
|
||||
{
|
||||
return (__uint128_t)a >> n;
|
||||
}
|
||||
|
||||
static inline Int128 int128_lshift(Int128 a, int n)
|
||||
{
|
||||
return a << n;
|
||||
}
|
||||
|
||||
static inline Int128 int128_add(Int128 a, Int128 b)
|
||||
{
|
||||
return a + b;
|
||||
}
|
||||
|
||||
static inline Int128 int128_neg(Int128 a)
|
||||
{
|
||||
return -a;
|
||||
}
|
||||
|
||||
static inline Int128 int128_sub(Int128 a, Int128 b)
|
||||
{
|
||||
return a - b;
|
||||
}
|
||||
|
||||
static inline bool int128_nonneg(Int128 a)
|
||||
{
|
||||
return a >= 0;
|
||||
}
|
||||
|
||||
static inline bool int128_eq(Int128 a, Int128 b)
|
||||
{
|
||||
return a == b;
|
||||
}
|
||||
|
||||
static inline bool int128_ne(Int128 a, Int128 b)
|
||||
{
|
||||
return a != b;
|
||||
}
|
||||
|
||||
static inline bool int128_ge(Int128 a, Int128 b)
|
||||
{
|
||||
return a >= b;
|
||||
}
|
||||
|
||||
static inline bool int128_uge(Int128 a, Int128 b)
|
||||
{
|
||||
return ((__uint128_t)a) >= ((__uint128_t)b);
|
||||
}
|
||||
|
||||
static inline bool int128_lt(Int128 a, Int128 b)
|
||||
{
|
||||
return a < b;
|
||||
}
|
||||
|
||||
static inline bool int128_ult(Int128 a, Int128 b)
|
||||
{
|
||||
return (__uint128_t)a < (__uint128_t)b;
|
||||
}
|
||||
|
||||
static inline bool int128_le(Int128 a, Int128 b)
|
||||
{
|
||||
return a <= b;
|
||||
}
|
||||
|
||||
static inline bool int128_gt(Int128 a, Int128 b)
|
||||
{
|
||||
return a > b;
|
||||
}
|
||||
|
||||
static inline bool int128_nz(Int128 a)
|
||||
{
|
||||
return a != 0;
|
||||
}
|
||||
|
||||
static inline Int128 int128_min(Int128 a, Int128 b)
|
||||
{
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
static inline Int128 int128_max(Int128 a, Int128 b)
|
||||
{
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
static inline void int128_addto(Int128 *a, Int128 b)
|
||||
{
|
||||
*a += b;
|
||||
}
|
||||
|
||||
static inline void int128_subfrom(Int128 *a, Int128 b)
|
||||
{
|
||||
*a -= b;
|
||||
}
|
||||
|
||||
static inline Int128 bswap128(Int128 a)
|
||||
{
|
||||
#if __has_builtin(__builtin_bswap128)
|
||||
return __builtin_bswap128(a);
|
||||
#else
|
||||
return int128_make128(__builtin_bswap64(int128_gethi(a)),
|
||||
__builtin_bswap64(int128_getlo(a)));
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline int clz128(Int128 a)
|
||||
{
|
||||
if (a >> 64) {
|
||||
return __builtin_clzll(a >> 64);
|
||||
} else {
|
||||
return (a) ? __builtin_clzll((uint64_t)a) + 64 : 128;
|
||||
}
|
||||
}
|
||||
|
||||
static inline Int128 int128_divu(Int128 a, Int128 b)
|
||||
{
|
||||
return (__uint128_t)a / (__uint128_t)b;
|
||||
}
|
||||
|
||||
static inline Int128 int128_remu(Int128 a, Int128 b)
|
||||
{
|
||||
return (__uint128_t)a % (__uint128_t)b;
|
||||
}
|
||||
|
||||
static inline Int128 int128_divs(Int128 a, Int128 b)
|
||||
{
|
||||
return a / b;
|
||||
}
|
||||
|
||||
static inline Int128 int128_rems(Int128 a, Int128 b)
|
||||
{
|
||||
return a % b;
|
||||
}
|
||||
|
||||
#else /* !CONFIG_INT128 */
|
||||
|
||||
typedef struct Int128 Int128;
|
||||
typedef struct Int128 __attribute__((aligned(16))) Int128Aligned;
|
||||
|
||||
/*
|
||||
* We guarantee that the in-memory byte representation of an
|
||||
* Int128 is that of a host-endian-order 128-bit integer
|
||||
* (whether using this struct or the __int128_t version of the type).
|
||||
* Some code using this type relies on this (eg when copying it into
|
||||
* guest memory or a gdb protocol buffer, or by using Int128 in
|
||||
* a union with other integer types).
|
||||
*/
|
||||
struct Int128 {
|
||||
#if HOST_BIG_ENDIAN
|
||||
int64_t hi;
|
||||
uint64_t lo;
|
||||
#else
|
||||
uint64_t lo;
|
||||
int64_t hi;
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline Int128 int128_make64(uint64_t a)
|
||||
{
|
||||
return (Int128) { .lo = a, .hi = 0 };
|
||||
}
|
||||
|
||||
static inline Int128 int128_makes64(int64_t a)
|
||||
{
|
||||
return (Int128) { .lo = a, .hi = a >> 63 };
|
||||
}
|
||||
|
||||
static inline Int128 int128_make128(uint64_t lo, uint64_t hi)
|
||||
{
|
||||
return (Int128) { .lo = lo, .hi = hi };
|
||||
}
|
||||
|
||||
static inline uint64_t int128_get64(Int128 a)
|
||||
{
|
||||
assert(!a.hi);
|
||||
return a.lo;
|
||||
}
|
||||
|
||||
static inline uint64_t int128_getlo(Int128 a)
|
||||
{
|
||||
return a.lo;
|
||||
}
|
||||
|
||||
static inline int64_t int128_gethi(Int128 a)
|
||||
{
|
||||
return a.hi;
|
||||
}
|
||||
|
||||
static inline Int128 int128_zero(void)
|
||||
{
|
||||
return int128_make64(0);
|
||||
}
|
||||
|
||||
static inline Int128 int128_one(void)
|
||||
{
|
||||
return int128_make64(1);
|
||||
}
|
||||
|
||||
static inline Int128 int128_2_64(void)
|
||||
{
|
||||
return int128_make128(0, 1);
|
||||
}
|
||||
|
||||
static inline Int128 int128_exts64(int64_t a)
|
||||
{
|
||||
return int128_make128(a, (a < 0) ? -1 : 0);
|
||||
}
|
||||
|
||||
static inline Int128 int128_not(Int128 a)
|
||||
{
|
||||
return int128_make128(~a.lo, ~a.hi);
|
||||
}
|
||||
|
||||
static inline Int128 int128_and(Int128 a, Int128 b)
|
||||
{
|
||||
return int128_make128(a.lo & b.lo, a.hi & b.hi);
|
||||
}
|
||||
|
||||
static inline Int128 int128_or(Int128 a, Int128 b)
|
||||
{
|
||||
return int128_make128(a.lo | b.lo, a.hi | b.hi);
|
||||
}
|
||||
|
||||
static inline Int128 int128_xor(Int128 a, Int128 b)
|
||||
{
|
||||
return int128_make128(a.lo ^ b.lo, a.hi ^ b.hi);
|
||||
}
|
||||
|
||||
static inline Int128 int128_rshift(Int128 a, int n)
|
||||
{
|
||||
int64_t h;
|
||||
if (!n) {
|
||||
return a;
|
||||
}
|
||||
h = a.hi >> (n & 63);
|
||||
if (n >= 64) {
|
||||
return int128_make128(h, h >> 63);
|
||||
} else {
|
||||
return int128_make128((a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h);
|
||||
}
|
||||
}
|
||||
|
||||
static inline Int128 int128_urshift(Int128 a, int n)
|
||||
{
|
||||
uint64_t h = a.hi;
|
||||
if (!n) {
|
||||
return a;
|
||||
}
|
||||
h = h >> (n & 63);
|
||||
if (n >= 64) {
|
||||
return int128_make64(h);
|
||||
} else {
|
||||
return int128_make128((a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h);
|
||||
}
|
||||
}
|
||||
|
||||
static inline Int128 int128_lshift(Int128 a, int n)
|
||||
{
|
||||
uint64_t l = a.lo << (n & 63);
|
||||
if (n >= 64) {
|
||||
return int128_make128(0, l);
|
||||
} else if (n > 0) {
|
||||
return int128_make128(l, (a.hi << n) | (a.lo >> (64 - n)));
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
static inline Int128 int128_add(Int128 a, Int128 b)
|
||||
{
|
||||
uint64_t lo = a.lo + b.lo;
|
||||
|
||||
/* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64). Hence,
|
||||
* a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo.
|
||||
* Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k.
|
||||
*
|
||||
* So the carry is lo < a.lo.
|
||||
*/
|
||||
return int128_make128(lo, (uint64_t)a.hi + b.hi + (lo < a.lo));
|
||||
}
|
||||
|
||||
static inline Int128 int128_neg(Int128 a)
|
||||
{
|
||||
uint64_t lo = -a.lo;
|
||||
return int128_make128(lo, ~(uint64_t)a.hi + !lo);
|
||||
}
|
||||
|
||||
static inline Int128 int128_sub(Int128 a, Int128 b)
|
||||
{
|
||||
return int128_make128(a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo));
|
||||
}
|
||||
|
||||
static inline bool int128_nonneg(Int128 a)
|
||||
{
|
||||
return a.hi >= 0;
|
||||
}
|
||||
|
||||
static inline bool int128_eq(Int128 a, Int128 b)
|
||||
{
|
||||
return a.lo == b.lo && a.hi == b.hi;
|
||||
}
|
||||
|
||||
static inline bool int128_ne(Int128 a, Int128 b)
|
||||
{
|
||||
return !int128_eq(a, b);
|
||||
}
|
||||
|
||||
static inline bool int128_ge(Int128 a, Int128 b)
|
||||
{
|
||||
return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo);
|
||||
}
|
||||
|
||||
static inline bool int128_uge(Int128 a, Int128 b)
|
||||
{
|
||||
return (uint64_t)a.hi > (uint64_t)b.hi || (a.hi == b.hi && a.lo >= b.lo);
|
||||
}
|
||||
|
||||
static inline bool int128_lt(Int128 a, Int128 b)
|
||||
{
|
||||
return !int128_ge(a, b);
|
||||
}
|
||||
|
||||
static inline bool int128_ult(Int128 a, Int128 b)
|
||||
{
|
||||
return !int128_uge(a, b);
|
||||
}
|
||||
|
||||
static inline bool int128_le(Int128 a, Int128 b)
|
||||
{
|
||||
return int128_ge(b, a);
|
||||
}
|
||||
|
||||
static inline bool int128_gt(Int128 a, Int128 b)
|
||||
{
|
||||
return !int128_le(a, b);
|
||||
}
|
||||
|
||||
static inline bool int128_nz(Int128 a)
|
||||
{
|
||||
return a.lo || a.hi;
|
||||
}
|
||||
|
||||
static inline Int128 int128_min(Int128 a, Int128 b)
|
||||
{
|
||||
return int128_le(a, b) ? a : b;
|
||||
}
|
||||
|
||||
static inline Int128 int128_max(Int128 a, Int128 b)
|
||||
{
|
||||
return int128_ge(a, b) ? a : b;
|
||||
}
|
||||
|
||||
static inline void int128_addto(Int128 *a, Int128 b)
|
||||
{
|
||||
*a = int128_add(*a, b);
|
||||
}
|
||||
|
||||
static inline void int128_subfrom(Int128 *a, Int128 b)
|
||||
{
|
||||
*a = int128_sub(*a, b);
|
||||
}
|
||||
|
||||
static inline Int128 bswap128(Int128 a)
|
||||
{
|
||||
return int128_make128(__builtin_bswap64(a.hi), __builtin_bswap64(a.lo));
|
||||
}
|
||||
|
||||
static inline int clz128(Int128 a)
|
||||
{
|
||||
if (a.hi) {
|
||||
return __builtin_clzll(a.hi);
|
||||
} else {
|
||||
return (a.lo) ? __builtin_clzll(a.lo) + 64 : 128;
|
||||
}
|
||||
}
|
||||
|
||||
Int128 int128_divu(Int128, Int128);
|
||||
Int128 int128_remu(Int128, Int128);
|
||||
Int128 int128_divs(Int128, Int128);
|
||||
Int128 int128_rems(Int128, Int128);
|
||||
#endif /* CONFIG_INT128 && !CONFIG_TCG_INTERPRETER */
|
||||
|
||||
static inline void bswap128s(Int128 *s)
|
||||
{
|
||||
*s = bswap128(*s);
|
||||
}
|
||||
|
||||
#define UINT128_MAX int128_make128(~0LL, ~0LL)
|
||||
#define INT128_MAX int128_make128(UINT64_MAX, INT64_MAX)
|
||||
#define INT128_MIN int128_make128(0, INT64_MIN)
|
||||
|
||||
/*
|
||||
* When compiler supports a 128-bit type, define a combination of
|
||||
* a possible structure and the native types. Ease parameter passing
|
||||
* via use of the transparent union extension.
|
||||
*/
|
||||
#ifdef CONFIG_INT128_TYPE
|
||||
typedef union {
|
||||
__uint128_t u;
|
||||
__int128_t i;
|
||||
Int128 s;
|
||||
} Int128Alias __attribute__((transparent_union));
|
||||
#else
|
||||
typedef Int128 Int128Alias;
|
||||
#endif /* CONFIG_INT128_TYPE */
|
||||
|
||||
#endif /* INT128_H */
|
||||
@@ -0,0 +1,99 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Interval trees.
|
||||
*
|
||||
* Derived from include/linux/interval_tree.h and its dependencies.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_INTERVAL_TREE_H
|
||||
#define QEMU_INTERVAL_TREE_H
|
||||
|
||||
/*
|
||||
* For now, don't expose Linux Red-Black Trees separately, but retain the
|
||||
* separate type definitions to keep the implementation sane, and allow
|
||||
* the possibility of disentangling them later.
|
||||
*/
|
||||
typedef struct RBNode
|
||||
{
|
||||
/* Encodes parent with color in the lsb. */
|
||||
uintptr_t rb_parent_color;
|
||||
struct RBNode *rb_right;
|
||||
struct RBNode *rb_left;
|
||||
} RBNode;
|
||||
|
||||
typedef struct RBRoot
|
||||
{
|
||||
RBNode *rb_node;
|
||||
} RBRoot;
|
||||
|
||||
typedef struct RBRootLeftCached {
|
||||
RBRoot rb_root;
|
||||
RBNode *rb_leftmost;
|
||||
} RBRootLeftCached;
|
||||
|
||||
typedef struct IntervalTreeNode
|
||||
{
|
||||
RBNode rb;
|
||||
|
||||
uint64_t start; /* Start of interval */
|
||||
uint64_t last; /* Last location _in_ interval */
|
||||
uint64_t subtree_last;
|
||||
} IntervalTreeNode;
|
||||
|
||||
typedef RBRootLeftCached IntervalTreeRoot;
|
||||
|
||||
/**
|
||||
* interval_tree_is_empty
|
||||
* @root: root of the tree.
|
||||
*
|
||||
* Returns true if the tree contains no nodes.
|
||||
*/
|
||||
static inline bool interval_tree_is_empty(const IntervalTreeRoot *root)
|
||||
{
|
||||
return root->rb_root.rb_node == NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* interval_tree_insert
|
||||
* @node: node to insert,
|
||||
* @root: root of the tree.
|
||||
*
|
||||
* Insert @node into @root, and rebalance.
|
||||
*/
|
||||
void interval_tree_insert(IntervalTreeNode *node, IntervalTreeRoot *root);
|
||||
|
||||
/**
|
||||
* interval_tree_remove
|
||||
* @node: node to remove,
|
||||
* @root: root of the tree.
|
||||
*
|
||||
* Remove @node from @root, and rebalance.
|
||||
*/
|
||||
void interval_tree_remove(IntervalTreeNode *node, IntervalTreeRoot *root);
|
||||
|
||||
/**
|
||||
* interval_tree_iter_first:
|
||||
* @root: root of the tree,
|
||||
* @start, @last: the inclusive interval [start, last].
|
||||
*
|
||||
* Locate the "first" of a set of nodes within the tree at @root
|
||||
* that overlap the interval, where "first" is sorted by start.
|
||||
* Returns NULL if no overlap found.
|
||||
*/
|
||||
IntervalTreeNode *interval_tree_iter_first(IntervalTreeRoot *root,
|
||||
uint64_t start, uint64_t last);
|
||||
|
||||
/**
|
||||
* interval_tree_iter_next:
|
||||
* @node: previous search result
|
||||
* @start, @last: the inclusive interval [start, last].
|
||||
*
|
||||
* Locate the "next" of a set of nodes within the tree that overlap the
|
||||
* interval; @next is the result of a previous call to
|
||||
* interval_tree_iter_{first,next}. Returns NULL if @next was the last
|
||||
* node in the set.
|
||||
*/
|
||||
IntervalTreeNode *interval_tree_iter_next(IntervalTreeNode *node,
|
||||
uint64_t start, uint64_t last);
|
||||
|
||||
#endif /* QEMU_INTERVAL_TREE_H */
|
||||
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Helpers for using (partial) iovecs.
|
||||
*
|
||||
* Copyright (c) 2024 Seagate Technology LLC and/or its Affiliates
|
||||
* Copyright (C) 2010 Red Hat, Inc.
|
||||
*
|
||||
* Author(s):
|
||||
* Amit Shah <[email protected]>
|
||||
* Michael Tokarev <[email protected]>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef IOV_H
|
||||
#define IOV_H
|
||||
|
||||
/**
|
||||
* count and return data size, in bytes, of an iovec
|
||||
* starting at `iov' of `iov_cnt' number of elements.
|
||||
*/
|
||||
size_t iov_size(const struct iovec *iov, const unsigned int iov_cnt);
|
||||
|
||||
/**
|
||||
* Copy from single continuous buffer to scatter-gather vector of buffers
|
||||
* (iovec) and back like memcpy() between two continuous memory regions.
|
||||
* Data in single continuous buffer starting at address `buf' and
|
||||
* `bytes' bytes long will be copied to/from an iovec `iov' with
|
||||
* `iov_cnt' number of elements, starting at byte position `offset'
|
||||
* within the iovec. If the iovec does not contain enough space,
|
||||
* only part of data will be copied, up to the end of the iovec.
|
||||
* Number of bytes actually copied will be returned, which is
|
||||
* min(bytes, iov_size(iov)-offset)
|
||||
* Returns 0 when `offset' points to the outside of iovec.
|
||||
*/
|
||||
size_t iov_from_buf_full(const struct iovec *iov, unsigned int iov_cnt,
|
||||
size_t offset, const void *buf, size_t bytes);
|
||||
size_t iov_to_buf_full(const struct iovec *iov, const unsigned int iov_cnt,
|
||||
size_t offset, void *buf, size_t bytes);
|
||||
|
||||
static inline size_t
|
||||
iov_from_buf(const struct iovec *iov, unsigned int iov_cnt,
|
||||
size_t offset, const void *buf, size_t bytes)
|
||||
{
|
||||
if (__builtin_constant_p(bytes) && iov_cnt &&
|
||||
offset <= iov[0].iov_len && bytes <= iov[0].iov_len - offset) {
|
||||
memcpy(iov[0].iov_base + offset, buf, bytes);
|
||||
return bytes;
|
||||
} else {
|
||||
return iov_from_buf_full(iov, iov_cnt, offset, buf, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt,
|
||||
size_t offset, void *buf, size_t bytes)
|
||||
{
|
||||
if (__builtin_constant_p(bytes) && iov_cnt &&
|
||||
offset <= iov[0].iov_len && bytes <= iov[0].iov_len - offset) {
|
||||
memcpy(buf, iov[0].iov_base + offset, bytes);
|
||||
return bytes;
|
||||
} else {
|
||||
return iov_to_buf_full(iov, iov_cnt, offset, buf, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set data bytes pointed out by iovec `iov' of size `iov_cnt' elements,
|
||||
* starting at byte offset `start', to value `fillc', repeating it
|
||||
* `bytes' number of times.
|
||||
* If `bytes' is large enough, only last bytes portion of iovec,
|
||||
* up to the end of it, will be filled with the specified value.
|
||||
* Function return actual number of bytes processed, which is
|
||||
* min(size, iov_size(iov) - offset).
|
||||
* Returns 0 when `offset' points to the outside of iovec.
|
||||
*/
|
||||
size_t iov_memset(const struct iovec *iov, const unsigned int iov_cnt,
|
||||
size_t offset, int fillc, size_t bytes);
|
||||
|
||||
/*
|
||||
* Send/recv data from/to iovec buffers directly, with the provided
|
||||
* socket flags.
|
||||
*
|
||||
* `offset' bytes in the beginning of iovec buffer are skipped and
|
||||
* next `bytes' bytes are used, which must be within data of iovec.
|
||||
*
|
||||
* r = iov_send_recv_with_flags(sockfd, sockflags, iov, iovcnt,
|
||||
* offset, bytes, true);
|
||||
*
|
||||
* is logically equivalent to
|
||||
*
|
||||
* char *buf = malloc(bytes);
|
||||
* iov_to_buf(iov, iovcnt, offset, buf, bytes);
|
||||
* r = send(sockfd, buf, bytes, sockflags);
|
||||
* free(buf);
|
||||
*
|
||||
* For iov_send_recv_with_flags() _whole_ area being sent or received
|
||||
* should be within the iovec, not only beginning of it.
|
||||
*/
|
||||
ssize_t iov_send_recv_with_flags(int sockfd, int sockflags,
|
||||
const struct iovec *iov,
|
||||
unsigned iov_cnt, size_t offset,
|
||||
size_t bytes,
|
||||
bool do_send);
|
||||
|
||||
/*
|
||||
* Send/recv data from/to iovec buffers directly
|
||||
*
|
||||
* `offset' bytes in the beginning of iovec buffer are skipped and
|
||||
* next `bytes' bytes are used, which must be within data of iovec.
|
||||
*
|
||||
* r = iov_send_recv(sockfd, iov, iovcnt, offset, bytes, true);
|
||||
*
|
||||
* is logically equivalent to
|
||||
*
|
||||
* char *buf = malloc(bytes);
|
||||
* iov_to_buf(iov, iovcnt, offset, buf, bytes);
|
||||
* r = send(sockfd, buf, bytes, 0);
|
||||
* free(buf);
|
||||
*
|
||||
* For iov_send_recv() _whole_ area being sent or received
|
||||
* should be within the iovec, not only beginning of it.
|
||||
*/
|
||||
ssize_t iov_send_recv(int sockfd, const struct iovec *iov, unsigned iov_cnt,
|
||||
size_t offset, size_t bytes, bool do_send);
|
||||
#define iov_recv(sockfd, iov, iov_cnt, offset, bytes) \
|
||||
iov_send_recv(sockfd, iov, iov_cnt, offset, bytes, false)
|
||||
#define iov_send(sockfd, iov, iov_cnt, offset, bytes) \
|
||||
iov_send_recv(sockfd, iov, iov_cnt, offset, bytes, true)
|
||||
|
||||
/**
|
||||
* Produce a text hexdump of iovec `iov' with `iov_cnt' number of elements
|
||||
* in file `fp', prefixing each line with `prefix' and processing not more
|
||||
* than `limit' data bytes.
|
||||
*/
|
||||
void iov_hexdump(const struct iovec *iov, const unsigned int iov_cnt,
|
||||
FILE *fp, const char *prefix, size_t limit);
|
||||
|
||||
/*
|
||||
* Partial copy of vector from iov to dst_iov (data is not copied).
|
||||
* dst_iov overlaps iov at a specified offset.
|
||||
* size of dst_iov is at most bytes. dst vector count is returned.
|
||||
*/
|
||||
unsigned iov_copy(struct iovec *dst_iov, unsigned int dst_iov_cnt,
|
||||
const struct iovec *iov, unsigned int iov_cnt,
|
||||
size_t offset, size_t bytes);
|
||||
|
||||
/*
|
||||
* Remove a given number of bytes from the front or back of a vector.
|
||||
* This may update iov and/or iov_cnt to exclude iovec elements that are
|
||||
* no longer required.
|
||||
*
|
||||
* The number of bytes actually discarded is returned. This number may be
|
||||
* smaller than requested if the vector is too small.
|
||||
*/
|
||||
size_t iov_discard_front(struct iovec **iov, unsigned int *iov_cnt,
|
||||
size_t bytes);
|
||||
size_t iov_discard_back(struct iovec *iov, unsigned int *iov_cnt,
|
||||
size_t bytes);
|
||||
|
||||
/* Information needed to undo an iov_discard_*() operation */
|
||||
typedef struct {
|
||||
struct iovec *modified_iov;
|
||||
struct iovec orig;
|
||||
} IOVDiscardUndo;
|
||||
|
||||
/*
|
||||
* Undo an iov_discard_front_undoable() or iov_discard_back_undoable()
|
||||
* operation. If multiple operations are made then each one needs a separate
|
||||
* IOVDiscardUndo and iov_discard_undo() must be called in the reverse order
|
||||
* that the operations were made.
|
||||
*/
|
||||
void iov_discard_undo(IOVDiscardUndo *undo);
|
||||
|
||||
/*
|
||||
* Undoable versions of iov_discard_front() and iov_discard_back(). Use
|
||||
* iov_discard_undo() to reset to the state before the discard operations.
|
||||
*/
|
||||
size_t iov_discard_front_undoable(struct iovec **iov, unsigned int *iov_cnt,
|
||||
size_t bytes, IOVDiscardUndo *undo);
|
||||
size_t iov_discard_back_undoable(struct iovec *iov, unsigned int *iov_cnt,
|
||||
size_t bytes, IOVDiscardUndo *undo);
|
||||
|
||||
typedef struct QEMUIOVector {
|
||||
struct iovec *iov;
|
||||
int niov;
|
||||
|
||||
/*
|
||||
* For external @iov (qemu_iovec_init_external()) or allocated @iov
|
||||
* (qemu_iovec_init()), @size is the cumulative size of iovecs and
|
||||
* @local_iov is invalid and unused.
|
||||
*
|
||||
* For embedded @iov (QEMU_IOVEC_INIT_BUF() or qemu_iovec_init_buf()),
|
||||
* @iov is equal to &@local_iov, and @size is valid, as it has same
|
||||
* offset and type as @local_iov.iov_len, which is guaranteed by
|
||||
* static assertion below.
|
||||
*
|
||||
* @nalloc is always valid and is -1 both for embedded and external
|
||||
* cases. It is included in the union only to ensure the padding prior
|
||||
* to the @size field will not result in a 0-length array.
|
||||
*/
|
||||
union {
|
||||
struct {
|
||||
int nalloc;
|
||||
struct iovec local_iov;
|
||||
};
|
||||
struct {
|
||||
char __pad[sizeof(int) + offsetof(struct iovec, iov_len)];
|
||||
size_t size;
|
||||
};
|
||||
};
|
||||
} QEMUIOVector;
|
||||
|
||||
QEMU_BUILD_BUG_ON(offsetof(QEMUIOVector, size) !=
|
||||
offsetof(QEMUIOVector, local_iov.iov_len));
|
||||
|
||||
#define QEMU_IOVEC_INIT_BUF(self, buf, len) \
|
||||
{ \
|
||||
.iov = &(self).local_iov, \
|
||||
.niov = 1, \
|
||||
.nalloc = -1, \
|
||||
.local_iov = { \
|
||||
.iov_base = (void *)(buf), /* cast away const */ \
|
||||
.iov_len = (len), \
|
||||
}, \
|
||||
}
|
||||
|
||||
/*
|
||||
* qemu_iovec_init_buf
|
||||
*
|
||||
* Initialize embedded QEMUIOVector.
|
||||
*
|
||||
* Note: "const" is used over @buf pointer to make it simple to pass
|
||||
* const pointers, appearing in read functions. Then this "const" is
|
||||
* cast away by QEMU_IOVEC_INIT_BUF().
|
||||
*/
|
||||
static inline void qemu_iovec_init_buf(QEMUIOVector *qiov,
|
||||
const void *buf, size_t len)
|
||||
{
|
||||
*qiov = (QEMUIOVector) QEMU_IOVEC_INIT_BUF(*qiov, buf, len);
|
||||
}
|
||||
|
||||
static inline void *qemu_iovec_buf(QEMUIOVector *qiov)
|
||||
{
|
||||
/* Only supports embedded iov */
|
||||
assert(qiov->nalloc == -1 && qiov->iov == &qiov->local_iov);
|
||||
|
||||
return qiov->local_iov.iov_base;
|
||||
}
|
||||
|
||||
void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint);
|
||||
void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov);
|
||||
void qemu_iovec_init_slice(QEMUIOVector *qiov, QEMUIOVector *source,
|
||||
size_t offset, size_t len);
|
||||
struct iovec *qemu_iovec_slice(QEMUIOVector *qiov,
|
||||
size_t offset, size_t len,
|
||||
size_t *head, size_t *tail, int *niov);
|
||||
int qemu_iovec_subvec_niov(QEMUIOVector *qiov, size_t offset, size_t len);
|
||||
void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len);
|
||||
void qemu_iovec_concat(QEMUIOVector *dst,
|
||||
QEMUIOVector *src, size_t soffset, size_t sbytes);
|
||||
size_t qemu_iovec_concat_iov(QEMUIOVector *dst,
|
||||
struct iovec *src_iov, unsigned int src_cnt,
|
||||
size_t soffset, size_t sbytes);
|
||||
bool qemu_iovec_is_zero(QEMUIOVector *qiov, size_t qiov_offeset, size_t bytes);
|
||||
void qemu_iovec_destroy(QEMUIOVector *qiov);
|
||||
void qemu_iovec_reset(QEMUIOVector *qiov);
|
||||
size_t qemu_iovec_to_buf(QEMUIOVector *qiov, size_t offset,
|
||||
void *buf, size_t bytes);
|
||||
size_t qemu_iovec_from_buf(QEMUIOVector *qiov, size_t offset,
|
||||
const void *buf, size_t bytes);
|
||||
size_t qemu_iovec_memset(QEMUIOVector *qiov, size_t offset,
|
||||
int fillc, size_t bytes);
|
||||
ssize_t qemu_iovec_compare(QEMUIOVector *a, QEMUIOVector *b);
|
||||
void qemu_iovec_clone(QEMUIOVector *dest, const QEMUIOVector *src, void *buf);
|
||||
void qemu_iovec_discard_back(QEMUIOVector *qiov, size_t bytes);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* An very simplified iova tree implementation based on GTree.
|
||||
*
|
||||
* Copyright 2018 Red Hat, Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Peter Xu <[email protected]>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
*/
|
||||
#ifndef IOVA_TREE_H
|
||||
#define IOVA_TREE_H
|
||||
|
||||
/*
|
||||
* Currently the iova tree will only allow to keep ranges
|
||||
* information, and no extra user data is allowed for each element. A
|
||||
* benefit is that we can merge adjacent ranges internally within the
|
||||
* tree. It can save a lot of memory when the ranges are split but
|
||||
* mostly continuous.
|
||||
*
|
||||
* Note that current implementation does not provide any thread
|
||||
* protections. Callers of the iova tree should be responsible
|
||||
* for the thread safety issue.
|
||||
*/
|
||||
|
||||
#include "system/memory.h"
|
||||
#include "exec/hwaddr.h"
|
||||
|
||||
#define IOVA_OK (0)
|
||||
#define IOVA_ERR_INVALID (-1) /* Invalid parameters */
|
||||
#define IOVA_ERR_OVERLAP (-2) /* IOVA range overlapped */
|
||||
#define IOVA_ERR_NOMEM (-3) /* Cannot allocate */
|
||||
|
||||
typedef struct IOVATree IOVATree;
|
||||
typedef struct DMAMap {
|
||||
hwaddr iova;
|
||||
hwaddr translated_addr;
|
||||
hwaddr size; /* Inclusive */
|
||||
IOMMUAccessFlags perm;
|
||||
} QEMU_PACKED DMAMap;
|
||||
typedef gboolean (*iova_tree_iterator)(DMAMap *map);
|
||||
|
||||
/**
|
||||
* gpa_tree_new:
|
||||
*
|
||||
* Create a new GPA->IOVA tree.
|
||||
*
|
||||
* Returns: the tree point on success, or NULL otherwise.
|
||||
*/
|
||||
IOVATree *gpa_tree_new(void);
|
||||
|
||||
/**
|
||||
* gpa_tree_insert:
|
||||
*
|
||||
* @tree: The GPA->IOVA tree we're inserting the mapping to
|
||||
* @map: The GPA->IOVA mapping to insert
|
||||
*
|
||||
* Inserts a GPA range to the GPA->IOVA tree. If there are overlapped
|
||||
* ranges, IOVA_ERR_OVERLAP will be returned.
|
||||
*
|
||||
* Return: 0 if successful, < 0 otherwise.
|
||||
*/
|
||||
int gpa_tree_insert(IOVATree *tree, const DMAMap *map);
|
||||
|
||||
/**
|
||||
* iova_tree_new:
|
||||
*
|
||||
* Create a new iova tree.
|
||||
*
|
||||
* Returns: the tree pointer when succeeded, or NULL if error.
|
||||
*/
|
||||
IOVATree *iova_tree_new(void);
|
||||
|
||||
/**
|
||||
* iova_tree_insert:
|
||||
*
|
||||
* @tree: the iova tree to insert
|
||||
* @map: the mapping to insert
|
||||
*
|
||||
* Insert an iova range to the tree. If there is overlapped
|
||||
* ranges, IOVA_ERR_OVERLAP will be returned.
|
||||
*
|
||||
* Return: 0 if succeeded, or <0 if error.
|
||||
*/
|
||||
int iova_tree_insert(IOVATree *tree, const DMAMap *map);
|
||||
|
||||
/**
|
||||
* iova_tree_remove:
|
||||
*
|
||||
* @tree: the iova tree to remove range from
|
||||
* @map: the map range to remove
|
||||
*
|
||||
* Remove mappings from the tree that are covered by the map range
|
||||
* provided. The range does not need to be exactly what has inserted,
|
||||
* all the mappings that are included in the provided range will be
|
||||
* removed from the tree. Here map->translated_addr is meaningless.
|
||||
*/
|
||||
void iova_tree_remove(IOVATree *tree, DMAMap map);
|
||||
|
||||
/**
|
||||
* iova_tree_find:
|
||||
*
|
||||
* @tree: the iova tree to search from
|
||||
* @map: the mapping to search
|
||||
*
|
||||
* Search for a mapping in the iova tree that iova overlaps with the
|
||||
* mapping range specified. Only the first found mapping will be
|
||||
* returned.
|
||||
*
|
||||
* Return: DMAMap pointer if found, or NULL if not found. Note that
|
||||
* the returned DMAMap pointer is maintained internally. User should
|
||||
* only read the content but never modify or free the content. Also,
|
||||
* user is responsible to make sure the pointer is valid (say, no
|
||||
* concurrent deletion in progress).
|
||||
*/
|
||||
const DMAMap *iova_tree_find(const IOVATree *tree, const DMAMap *map);
|
||||
|
||||
/**
|
||||
* iova_tree_find_iova:
|
||||
*
|
||||
* @tree: the iova tree to search from
|
||||
* @map: the mapping to search
|
||||
*
|
||||
* Search for a mapping in the iova tree that translated_addr overlaps with the
|
||||
* mapping range specified. Only the first found mapping will be
|
||||
* returned.
|
||||
*
|
||||
* Return: DMAMap pointer if found, or NULL if not found. Note that
|
||||
* the returned DMAMap pointer is maintained internally. User should
|
||||
* only read the content but never modify or free the content. Also,
|
||||
* user is responsible to make sure the pointer is valid (say, no
|
||||
* concurrent deletion in progress).
|
||||
*/
|
||||
const DMAMap *iova_tree_find_iova(const IOVATree *tree, const DMAMap *map);
|
||||
|
||||
/**
|
||||
* iova_tree_alloc_map:
|
||||
*
|
||||
* @tree: the iova tree to allocate from
|
||||
* @map: the new map (as translated addr & size) to allocate in the iova region
|
||||
* @iova_begin: the minimum address of the allocation
|
||||
* @iova_end: the maximum addressable direction of the allocation
|
||||
*
|
||||
* Allocates a new region of a given size, between iova_min and iova_max.
|
||||
*
|
||||
* Return: Same as iova_tree_insert, but cannot overlap and can return error if
|
||||
* iova tree is out of free contiguous range. The caller gets the assigned iova
|
||||
* in map->iova.
|
||||
*/
|
||||
int iova_tree_alloc_map(IOVATree *tree, DMAMap *map, hwaddr iova_begin,
|
||||
hwaddr iova_end);
|
||||
|
||||
/**
|
||||
* iova_tree_destroy:
|
||||
*
|
||||
* @tree: the iova tree to destroy
|
||||
*
|
||||
* Destroy an existing iova tree.
|
||||
*
|
||||
* Return: None.
|
||||
*/
|
||||
void iova_tree_destroy(IOVATree *tree);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,59 @@
|
||||
/* jhash.h: Jenkins hash support.
|
||||
*
|
||||
* Copyright (C) 2006. Bob Jenkins ([email protected])
|
||||
*
|
||||
* http://burtleburtle.net/bob/hash/
|
||||
*
|
||||
* These are the credits from Bob's sources:
|
||||
*
|
||||
* lookup3.c, by Bob Jenkins, May 2006, Public Domain.
|
||||
*
|
||||
* These are functions for producing 32-bit hashes for hash table lookup.
|
||||
* hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
|
||||
* are externally useful functions. Routines to test the hash are included
|
||||
* if SELF_TEST is defined. You can use this free for any purpose. It's in
|
||||
* the public domain. It has no warranty.
|
||||
*
|
||||
* Copyright (C) 2009-2010 Jozsef Kadlecsik ([email protected])
|
||||
*
|
||||
* I've modified Bob's hash to be useful in the Linux kernel, and
|
||||
* any bugs present are my fault.
|
||||
* Jozsef
|
||||
*/
|
||||
|
||||
#ifndef QEMU_JHASH_H
|
||||
#define QEMU_JHASH_H
|
||||
|
||||
#include "qemu/bitops.h"
|
||||
|
||||
/*
|
||||
* hashtable relation copy from linux kernel jhash
|
||||
*/
|
||||
|
||||
/* __jhash_mix -- mix 3 32-bit values reversibly. */
|
||||
#define __jhash_mix(a, b, c) \
|
||||
{ \
|
||||
a -= c; a ^= rol32(c, 4); c += b; \
|
||||
b -= a; b ^= rol32(a, 6); a += c; \
|
||||
c -= b; c ^= rol32(b, 8); b += a; \
|
||||
a -= c; a ^= rol32(c, 16); c += b; \
|
||||
b -= a; b ^= rol32(a, 19); a += c; \
|
||||
c -= b; c ^= rol32(b, 4); b += a; \
|
||||
}
|
||||
|
||||
/* __jhash_final - final mixing of 3 32-bit values (a,b,c) into c */
|
||||
#define __jhash_final(a, b, c) \
|
||||
{ \
|
||||
c ^= b; c -= rol32(b, 14); \
|
||||
a ^= c; a -= rol32(c, 11); \
|
||||
b ^= a; b -= rol32(a, 25); \
|
||||
c ^= b; c -= rol32(b, 16); \
|
||||
a ^= c; a -= rol32(c, 4); \
|
||||
b ^= a; b -= rol32(a, 14); \
|
||||
c ^= b; c -= rol32(b, 24); \
|
||||
}
|
||||
|
||||
/* An arbitrary initial parameter */
|
||||
#define JHASH_INITVAL 0xdeadbeef
|
||||
|
||||
#endif /* QEMU_JHASH_H */
|
||||
@@ -0,0 +1,736 @@
|
||||
/*
|
||||
* Declarations for background jobs
|
||||
*
|
||||
* Copyright (c) 2011 IBM Corp.
|
||||
* Copyright (c) 2012, 2018 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef JOB_H
|
||||
#define JOB_H
|
||||
|
||||
#include "qapi/qapi-types-job.h"
|
||||
#include "qemu/aiocb.h"
|
||||
#include "qemu/queue.h"
|
||||
#include "qemu/progress_meter.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "qemu/aio.h"
|
||||
#include "block/graph-lock.h"
|
||||
|
||||
typedef struct JobDriver JobDriver;
|
||||
typedef struct JobTxn JobTxn;
|
||||
|
||||
|
||||
/**
|
||||
* Long-running operation.
|
||||
*/
|
||||
typedef struct Job {
|
||||
|
||||
/* Fields set at initialization (job_create), and never modified */
|
||||
|
||||
/** The ID of the job. May be NULL for internal jobs. */
|
||||
char *id;
|
||||
|
||||
/**
|
||||
* The type of this job.
|
||||
* All callbacks are called with job_mutex *not* held.
|
||||
*/
|
||||
const JobDriver *driver;
|
||||
|
||||
/**
|
||||
* The coroutine that executes the job. If not NULL, it is reentered when
|
||||
* busy is false and the job is cancelled.
|
||||
* Initialized in job_start()
|
||||
*/
|
||||
Coroutine *co;
|
||||
|
||||
/** True if this job should automatically finalize itself */
|
||||
bool auto_finalize;
|
||||
|
||||
/** True if this job should automatically dismiss itself */
|
||||
bool auto_dismiss;
|
||||
|
||||
/**
|
||||
* The completion function that will be called when the job completes.
|
||||
*/
|
||||
BlockCompletionFunc *cb;
|
||||
|
||||
/** The opaque value that is passed to the completion function. */
|
||||
void *opaque;
|
||||
|
||||
/* ProgressMeter API is thread-safe */
|
||||
ProgressMeter progress;
|
||||
|
||||
/**
|
||||
* AioContext to run the job coroutine in.
|
||||
* The job Aiocontext can be read when holding *either*
|
||||
* the BQL (so we are in the main loop) or the job_mutex.
|
||||
* It can only be written when we hold *both* BQL
|
||||
* and the job_mutex.
|
||||
*/
|
||||
AioContext *aio_context;
|
||||
|
||||
|
||||
/** Protected by job_mutex */
|
||||
|
||||
/** Reference count of the block job */
|
||||
int refcnt;
|
||||
|
||||
/** Current state; See @JobStatus for details. */
|
||||
JobStatus status;
|
||||
|
||||
/**
|
||||
* Timer that is used by @job_sleep_ns. Accessed under job_mutex (in
|
||||
* job.c).
|
||||
*/
|
||||
QEMUTimer sleep_timer;
|
||||
|
||||
/**
|
||||
* Counter for pause request. If non-zero, the block job is either paused,
|
||||
* or if busy == true will pause itself as soon as possible.
|
||||
*/
|
||||
int pause_count;
|
||||
|
||||
/**
|
||||
* Set to false by the job while the coroutine has yielded and may be
|
||||
* re-entered by job_enter(). There may still be I/O or event loop activity
|
||||
* pending. Accessed under job_mutex.
|
||||
*
|
||||
* When the job is deferred to the main loop, busy is true as long as the
|
||||
* bottom half is still pending.
|
||||
*/
|
||||
bool busy;
|
||||
|
||||
/**
|
||||
* Set to true by the job while it is in a quiescent state, where
|
||||
* no I/O or event loop activity is pending.
|
||||
*/
|
||||
bool paused;
|
||||
|
||||
/**
|
||||
* Set to true if the job is paused by user. Can be unpaused with the
|
||||
* block-job-resume QMP command.
|
||||
*/
|
||||
bool user_paused;
|
||||
|
||||
/**
|
||||
* Set to true if the job should cancel itself. The flag must
|
||||
* always be tested just before toggling the busy flag from false
|
||||
* to true. After a job has been cancelled, it should only yield
|
||||
* if #aio_poll will ("sooner or later") reenter the coroutine.
|
||||
*/
|
||||
bool cancelled;
|
||||
|
||||
/**
|
||||
* Set to true if the job should abort immediately without waiting
|
||||
* for data to be in sync.
|
||||
*/
|
||||
bool force_cancel;
|
||||
|
||||
/** Set to true when the job has deferred work to the main loop. */
|
||||
bool deferred_to_main_loop;
|
||||
|
||||
/**
|
||||
* Return code from @run and/or @prepare callback(s).
|
||||
* Not final until the job has reached the CONCLUDED status.
|
||||
* 0 on success, -errno on failure.
|
||||
*/
|
||||
int ret;
|
||||
|
||||
/**
|
||||
* Error object for a failed job.
|
||||
* If job->ret is nonzero and an error object was not set, it will be set
|
||||
* to strerror(-job->ret) during job_completed.
|
||||
*/
|
||||
Error *err;
|
||||
|
||||
/** Notifiers called when a cancelled job is finalised */
|
||||
NotifierList on_finalize_cancelled;
|
||||
|
||||
/** Notifiers called when a successfully completed job is finalised */
|
||||
NotifierList on_finalize_completed;
|
||||
|
||||
/** Notifiers called when the job transitions to PENDING */
|
||||
NotifierList on_pending;
|
||||
|
||||
/** Notifiers called when the job transitions to READY */
|
||||
NotifierList on_ready;
|
||||
|
||||
/** Notifiers called when the job coroutine yields or terminates */
|
||||
NotifierList on_idle;
|
||||
|
||||
/** Element of the list of jobs */
|
||||
QLIST_ENTRY(Job) job_list;
|
||||
|
||||
/** Transaction this job is part of */
|
||||
JobTxn *txn;
|
||||
|
||||
/** Element of the list of jobs in a job transaction */
|
||||
QLIST_ENTRY(Job) txn_list;
|
||||
} Job;
|
||||
|
||||
/**
|
||||
* Callbacks and other information about a Job driver.
|
||||
* All callbacks are invoked with job_mutex *not* held.
|
||||
*/
|
||||
struct JobDriver {
|
||||
|
||||
/*
|
||||
* These fields are initialized when this object is created,
|
||||
* and are never changed afterwards
|
||||
*/
|
||||
|
||||
/** Derived Job struct size */
|
||||
size_t instance_size;
|
||||
|
||||
/** Enum describing the operation */
|
||||
JobType job_type;
|
||||
|
||||
/**
|
||||
* Mandatory: Entrypoint for the Coroutine.
|
||||
*
|
||||
* This callback will be invoked when moving from CREATED to RUNNING.
|
||||
*
|
||||
* If this callback returns nonzero, the job transaction it is part of is
|
||||
* aborted. If it returns zero, the job moves into the WAITING state. If it
|
||||
* is the last job to complete in its transaction, all jobs in the
|
||||
* transaction move from WAITING to PENDING.
|
||||
*
|
||||
* This callback must be run in the job's context.
|
||||
*/
|
||||
int coroutine_fn (*run)(Job *job, Error **errp);
|
||||
|
||||
/*
|
||||
* Functions run without regard to the BQL that may run in any
|
||||
* arbitrary thread. These functions do not need to be thread-safe
|
||||
* because the caller ensures that they are invoked from one
|
||||
* thread at time.
|
||||
*/
|
||||
|
||||
/**
|
||||
* If the callback is not NULL, it will be invoked when the job transitions
|
||||
* into the paused state. Paused jobs must not perform any asynchronous
|
||||
* I/O or event loop activity. This callback is used to quiesce jobs.
|
||||
*/
|
||||
void coroutine_fn (*pause)(Job *job);
|
||||
|
||||
/**
|
||||
* If the callback is not NULL, it will be invoked when the job transitions
|
||||
* out of the paused state. Any asynchronous I/O or event loop activity
|
||||
* should be restarted from this callback.
|
||||
*/
|
||||
void coroutine_fn (*resume)(Job *job);
|
||||
|
||||
/*
|
||||
* Global state (GS) API. These functions run under the BQL.
|
||||
*
|
||||
* See include/block/block-global-state.h for more information about
|
||||
* the GS API.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Called when the job is resumed by the user (i.e. user_paused becomes
|
||||
* false). .user_resume is called before .resume.
|
||||
*/
|
||||
void (*user_resume)(Job *job);
|
||||
|
||||
/**
|
||||
* Optional callback for job types whose completion must be triggered
|
||||
* manually.
|
||||
*/
|
||||
void (*complete)(Job *job, Error **errp);
|
||||
|
||||
/**
|
||||
* If the callback is not NULL, prepare will be invoked when all the jobs
|
||||
* belonging to the same transaction complete; or upon this job's completion
|
||||
* if it is not in a transaction.
|
||||
*
|
||||
* This callback will not be invoked if the job has already failed.
|
||||
* If it fails, abort and then clean will be called.
|
||||
*/
|
||||
int GRAPH_UNLOCKED_PTR (*prepare)(Job *job);
|
||||
|
||||
/**
|
||||
* If the callback is not NULL, it will be invoked when all the jobs
|
||||
* belonging to the same transaction complete; or upon this job's
|
||||
* completion if it is not in a transaction. Skipped if NULL.
|
||||
*
|
||||
* All jobs will complete with a call to either .commit() or .abort() but
|
||||
* never both.
|
||||
*/
|
||||
void (*commit)(Job *job);
|
||||
|
||||
/**
|
||||
* If the callback is not NULL, it will be invoked when any job in the
|
||||
* same transaction fails; or upon this job's failure (due to error or
|
||||
* cancellation) if it is not in a transaction. Skipped if NULL.
|
||||
*
|
||||
* All jobs will complete with a call to either .commit() or .abort() but
|
||||
* never both.
|
||||
*/
|
||||
void GRAPH_UNLOCKED_PTR (*abort)(Job *job);
|
||||
|
||||
/**
|
||||
* If the callback is not NULL, it will be invoked after a call to either
|
||||
* .commit() or .abort(). Regardless of which callback is invoked after
|
||||
* completion, .clean() will always be called, even if the job does not
|
||||
* belong to a transaction group.
|
||||
*/
|
||||
void (*clean)(Job *job);
|
||||
|
||||
/**
|
||||
* If the callback is not NULL, it will be invoked in job_cancel_async
|
||||
*
|
||||
* This function must return true if the job will be cancelled
|
||||
* immediately without any further I/O (mandatory if @force is
|
||||
* true), and false otherwise. This lets the generic job layer
|
||||
* know whether a job has been truly (force-)cancelled, or whether
|
||||
* it is just in a special completion mode (like mirror after
|
||||
* READY).
|
||||
* (If the callback is NULL, the job is assumed to terminate
|
||||
* without I/O.)
|
||||
*/
|
||||
bool (*cancel)(Job *job, bool force);
|
||||
|
||||
|
||||
/**
|
||||
* Called when the job is freed.
|
||||
*/
|
||||
void (*free)(Job *job);
|
||||
};
|
||||
|
||||
typedef enum JobCreateFlags {
|
||||
/* Default behavior */
|
||||
JOB_DEFAULT = 0x00,
|
||||
/* Job is not QMP-created and should not send QMP events */
|
||||
JOB_INTERNAL = 0x01,
|
||||
/* Job requires manual finalize step */
|
||||
JOB_MANUAL_FINALIZE = 0x02,
|
||||
/* Job requires manual dismiss step */
|
||||
JOB_MANUAL_DISMISS = 0x04,
|
||||
} JobCreateFlags;
|
||||
|
||||
extern QemuMutex job_mutex;
|
||||
|
||||
#define JOB_LOCK_GUARD() QEMU_LOCK_GUARD(&job_mutex)
|
||||
|
||||
#define WITH_JOB_LOCK_GUARD() WITH_QEMU_LOCK_GUARD(&job_mutex)
|
||||
|
||||
/**
|
||||
* job_lock:
|
||||
*
|
||||
* Take the mutex protecting the list of jobs and their status.
|
||||
* Most functions called by the monitor need to call job_lock
|
||||
* and job_unlock manually. On the other hand, function called
|
||||
* by the block jobs themselves and by the block layer will take the
|
||||
* lock for you.
|
||||
*/
|
||||
void job_lock(void);
|
||||
|
||||
/**
|
||||
* job_unlock:
|
||||
*
|
||||
* Release the mutex protecting the list of jobs and their status.
|
||||
*/
|
||||
void job_unlock(void);
|
||||
|
||||
/**
|
||||
* Allocate and return a new job transaction. Jobs can be added to the
|
||||
* transaction using job_txn_add_job().
|
||||
*
|
||||
* The transaction is automatically freed when the last job completes or is
|
||||
* cancelled.
|
||||
*
|
||||
* All jobs in the transaction either complete successfully or fail/cancel as a
|
||||
* group. Jobs wait for each other before completing. Cancelling one job
|
||||
* cancels all jobs in the transaction.
|
||||
*/
|
||||
JobTxn *job_txn_new(void);
|
||||
|
||||
/**
|
||||
* Release a reference that was previously acquired with job_txn_add_job or
|
||||
* job_txn_new. If it's the last reference to the object, it will be freed.
|
||||
*
|
||||
* Called with job lock *not* held.
|
||||
*/
|
||||
void job_txn_unref(JobTxn *txn);
|
||||
|
||||
/*
|
||||
* Same as job_txn_unref(), but called with job lock held.
|
||||
* Might release the lock temporarily.
|
||||
*/
|
||||
void job_txn_unref_locked(JobTxn *txn);
|
||||
|
||||
/**
|
||||
* Create a new long-running job and return it.
|
||||
* Called with job_mutex *not* held.
|
||||
*
|
||||
* @job_id: The id of the newly-created job, or %NULL for internal jobs
|
||||
* @driver: The class object for the newly-created job.
|
||||
* @txn: The transaction this job belongs to, if any. %NULL otherwise.
|
||||
* @ctx: The AioContext to run the job coroutine in.
|
||||
* @flags: Creation flags for the job. See @JobCreateFlags.
|
||||
* @cb: Completion function for the job.
|
||||
* @opaque: Opaque pointer value passed to @cb.
|
||||
* @errp: Error object.
|
||||
*/
|
||||
void *job_create(const char *job_id, const JobDriver *driver, JobTxn *txn,
|
||||
AioContext *ctx, int flags, BlockCompletionFunc *cb,
|
||||
void *opaque, Error **errp);
|
||||
|
||||
/**
|
||||
* Add a reference to Job refcnt, it will be decreased with job_unref, and then
|
||||
* be freed if it comes to be the last reference.
|
||||
*
|
||||
* Called with job lock held.
|
||||
*/
|
||||
void job_ref_locked(Job *job);
|
||||
|
||||
/**
|
||||
* Release a reference that was previously acquired with job_ref_locked() or
|
||||
* job_create(). If it's the last reference to the object, it will be freed.
|
||||
*
|
||||
* Called with job lock held.
|
||||
*/
|
||||
void job_unref_locked(Job *job);
|
||||
|
||||
/**
|
||||
* @job: The job that has made progress
|
||||
* @done: How much progress the job made since the last call
|
||||
*
|
||||
* Updates the progress counter of the job.
|
||||
*
|
||||
* May be called with mutex held or not held.
|
||||
*/
|
||||
void job_progress_update(Job *job, uint64_t done);
|
||||
|
||||
/**
|
||||
* @job: The job whose expected progress end value is set
|
||||
* @remaining: Missing progress (on top of the current progress counter value)
|
||||
* until the new expected end value is reached
|
||||
*
|
||||
* Sets the expected end value of the progress counter of a job so that a
|
||||
* completion percentage can be calculated when the progress is updated.
|
||||
*
|
||||
* May be called with mutex held or not held.
|
||||
*/
|
||||
void job_progress_set_remaining(Job *job, uint64_t remaining);
|
||||
|
||||
/**
|
||||
* @job: The job whose expected progress end value is updated
|
||||
* @delta: Value which is to be added to the current expected end
|
||||
* value
|
||||
*
|
||||
* Increases the expected end value of the progress counter of a job.
|
||||
* This is useful for parenthesis operations: If a job has to
|
||||
* conditionally perform a high-priority operation as part of its
|
||||
* progress, it calls this function with the expected operation's
|
||||
* length before, and job_progress_update() afterwards.
|
||||
* (So the operation acts as a parenthesis in regards to the main job
|
||||
* operation running in background.)
|
||||
*
|
||||
* May be called with mutex held or not held.
|
||||
*/
|
||||
void job_progress_increase_remaining(Job *job, uint64_t delta);
|
||||
|
||||
/**
|
||||
* Conditionally enter the job coroutine if the job is ready to run, not
|
||||
* already busy and fn() returns true. fn() is called while under the job_lock
|
||||
* critical section.
|
||||
*
|
||||
* Called with job lock held, but might release it temporarily.
|
||||
*/
|
||||
void job_enter_cond_locked(Job *job, bool(*fn)(Job *job));
|
||||
|
||||
/**
|
||||
* @job: A job that has not yet been started.
|
||||
*
|
||||
* Begins execution of a job.
|
||||
* Takes ownership of one reference to the job object.
|
||||
*
|
||||
* Called with job_mutex *not* held.
|
||||
*/
|
||||
void job_start(Job *job);
|
||||
|
||||
/**
|
||||
* @job: The job to enter.
|
||||
*
|
||||
* Continue the specified job by entering the coroutine.
|
||||
* Called with job_mutex *not* held.
|
||||
*/
|
||||
void job_enter(Job *job);
|
||||
|
||||
/**
|
||||
* @job: The job that is ready to pause.
|
||||
*
|
||||
* Pause now if job_pause() has been called. Jobs that perform lots of I/O
|
||||
* must call this between requests so that the job can be paused.
|
||||
*
|
||||
* Called with job_mutex *not* held.
|
||||
*/
|
||||
void coroutine_fn GRAPH_UNLOCKED job_pause_point(Job *job);
|
||||
|
||||
/**
|
||||
* @job: The job that calls the function.
|
||||
*
|
||||
* Yield the job coroutine.
|
||||
* Called with job_mutex *not* held.
|
||||
*/
|
||||
void coroutine_fn job_yield(Job *job);
|
||||
|
||||
/**
|
||||
* @job: The job that calls the function.
|
||||
* @ns: How many nanoseconds to stop for.
|
||||
*
|
||||
* Put the job to sleep (assuming that it wasn't canceled) for @ns
|
||||
* %QEMU_CLOCK_REALTIME nanoseconds. Canceling the job will immediately
|
||||
* interrupt the wait.
|
||||
*
|
||||
* Called with job_mutex *not* held.
|
||||
*/
|
||||
void coroutine_fn job_sleep_ns(Job *job, int64_t ns);
|
||||
|
||||
/** Returns the JobType of a given Job. */
|
||||
JobType job_type(const Job *job);
|
||||
|
||||
/** Returns the enum string for the JobType of a given Job. */
|
||||
const char *job_type_str(const Job *job);
|
||||
|
||||
/** Returns true if the job should not be visible to the management layer. */
|
||||
bool job_is_internal(Job *job);
|
||||
|
||||
/**
|
||||
* Returns whether the job is being cancelled.
|
||||
* Called with job_mutex *not* held.
|
||||
*/
|
||||
bool job_is_cancelled(Job *job);
|
||||
|
||||
/* Same as job_is_cancelled(), but called with job lock held. */
|
||||
bool job_is_cancelled_locked(Job *job);
|
||||
|
||||
/**
|
||||
* Returns whether the job is scheduled for cancellation (at an
|
||||
* indefinite point).
|
||||
* Called with job_mutex *not* held.
|
||||
*/
|
||||
bool job_cancel_requested(Job *job);
|
||||
|
||||
/**
|
||||
* Returns whether the job is in a completed state.
|
||||
* Called with job lock held.
|
||||
*/
|
||||
bool job_is_completed_locked(Job *job);
|
||||
|
||||
/**
|
||||
* Returns whether the job is ready to be completed.
|
||||
* Called with job_mutex *not* held.
|
||||
*/
|
||||
bool job_is_ready(Job *job);
|
||||
|
||||
/* Same as job_is_ready(), but called with job lock held. */
|
||||
bool job_is_ready_locked(Job *job);
|
||||
|
||||
/** Returns whether the job is paused. Called with job_mutex *not* held. */
|
||||
bool job_is_paused(Job *job);
|
||||
|
||||
/**
|
||||
* Request @job to pause at the next pause point. Must be paired with
|
||||
* job_resume(). If the job is supposed to be resumed by user action, call
|
||||
* job_user_pause_locked() instead.
|
||||
*
|
||||
* Called with job lock *not* held.
|
||||
*/
|
||||
void job_pause(Job *job);
|
||||
|
||||
/* Same as job_pause(), but called with job lock held. */
|
||||
void job_pause_locked(Job *job);
|
||||
|
||||
/** Resumes a @job paused with job_pause. Called with job lock *not* held. */
|
||||
void job_resume(Job *job);
|
||||
|
||||
/*
|
||||
* Same as job_resume(), but called with job lock held.
|
||||
* Might release the lock temporarily.
|
||||
*/
|
||||
void job_resume_locked(Job *job);
|
||||
|
||||
/**
|
||||
* Asynchronously pause the specified @job.
|
||||
* Do not allow a resume until a matching call to job_user_resume.
|
||||
* Called with job lock held.
|
||||
*/
|
||||
void job_user_pause_locked(Job *job, Error **errp);
|
||||
|
||||
/**
|
||||
* Returns true if the job is user-paused.
|
||||
* Called with job lock held.
|
||||
*/
|
||||
bool job_user_paused_locked(Job *job);
|
||||
|
||||
/**
|
||||
* Resume the specified @job.
|
||||
* Must be paired with a preceding job_user_pause_locked.
|
||||
* Called with job lock held, but might release it temporarily.
|
||||
*/
|
||||
void job_user_resume_locked(Job *job, Error **errp);
|
||||
|
||||
/**
|
||||
* Get the next element from the list of block jobs after @job, or the
|
||||
* first one if @job is %NULL.
|
||||
*
|
||||
* Returns the requested job, or %NULL if there are no more jobs left.
|
||||
* Called with job lock *not* held.
|
||||
*/
|
||||
Job *job_next(Job *job);
|
||||
|
||||
/* Same as job_next(), but called with job lock held. */
|
||||
Job *job_next_locked(Job *job);
|
||||
|
||||
/**
|
||||
* Get the job identified by @id (which must not be %NULL).
|
||||
*
|
||||
* Returns the requested job, or %NULL if it doesn't exist.
|
||||
* Called with job lock held.
|
||||
*/
|
||||
Job *job_get_locked(const char *id);
|
||||
|
||||
/**
|
||||
* Check whether the verb @verb can be applied to @job in its current state.
|
||||
* Returns 0 if the verb can be applied; otherwise errp is set and -EPERM
|
||||
* returned.
|
||||
*
|
||||
* Called with job lock held.
|
||||
*/
|
||||
int job_apply_verb_locked(Job *job, JobVerb verb, Error **errp);
|
||||
|
||||
/**
|
||||
* The @job could not be started, free it.
|
||||
* Called with job_mutex *not* held.
|
||||
*/
|
||||
void job_early_fail(Job *job);
|
||||
|
||||
/**
|
||||
* Moves the @job from RUNNING to READY.
|
||||
* Called with job_mutex *not* held.
|
||||
*/
|
||||
void job_transition_to_ready(Job *job);
|
||||
|
||||
/**
|
||||
* Asynchronously complete the specified @job.
|
||||
* Called with job lock held, but might release it temporarily.
|
||||
*/
|
||||
void job_complete_locked(Job *job, Error **errp);
|
||||
|
||||
/**
|
||||
* Asynchronously cancel the specified @job. If @force is true, the job should
|
||||
* be cancelled immediately without waiting for a consistent state.
|
||||
* Called with job lock held.
|
||||
*/
|
||||
void job_cancel_locked(Job *job, bool force);
|
||||
|
||||
/**
|
||||
* Cancels the specified job like job_cancel_locked(), but may refuse
|
||||
* to do so if the operation isn't meaningful in the current state of the job.
|
||||
* Called with job lock held.
|
||||
*/
|
||||
void job_user_cancel_locked(Job *job, bool force, Error **errp);
|
||||
|
||||
/**
|
||||
* Synchronously cancel the @job. The completion callback is called
|
||||
* before the function returns. If @force is false, the job may
|
||||
* actually complete instead of canceling itself; the circumstances
|
||||
* under which this happens depend on the kind of job that is active.
|
||||
*
|
||||
* Returns the return value from the job if the job actually completed
|
||||
* during the call, or -ECANCELED if it was canceled.
|
||||
*
|
||||
* Called with job_lock *not* held.
|
||||
*/
|
||||
int job_cancel_sync(Job *job, bool force);
|
||||
|
||||
/* Same as job_cancel_sync, but called with job lock held. */
|
||||
int job_cancel_sync_locked(Job *job, bool force);
|
||||
|
||||
/**
|
||||
* Synchronously force-cancels all jobs using job_cancel_sync_locked().
|
||||
*
|
||||
* Called with job_lock *not* held.
|
||||
*/
|
||||
void job_cancel_sync_all(void);
|
||||
|
||||
/**
|
||||
* @job: The job to be completed.
|
||||
* @errp: Error object which may be set by job_complete_locked(); this is not
|
||||
* necessarily set on every error, the job return value has to be
|
||||
* checked as well.
|
||||
*
|
||||
* Synchronously complete the job. The completion callback is called before the
|
||||
* function returns, unless it is NULL (which is permissible when using this
|
||||
* function).
|
||||
*
|
||||
* Returns the return value from the job.
|
||||
* Called with job_lock held.
|
||||
*/
|
||||
int job_complete_sync_locked(Job *job, Error **errp);
|
||||
|
||||
/**
|
||||
* For a @job that has finished its work and is pending awaiting explicit
|
||||
* acknowledgement to commit its work, this will commit that work.
|
||||
*
|
||||
* FIXME: Make the below statement universally true:
|
||||
* For jobs that support the manual workflow mode, all graph changes that occur
|
||||
* as a result will occur after this command and before a successful reply.
|
||||
*
|
||||
* Called with job lock held.
|
||||
*/
|
||||
void job_finalize_locked(Job *job, Error **errp);
|
||||
|
||||
/**
|
||||
* Remove the concluded @job from the query list and resets the passed pointer
|
||||
* to %NULL. Returns an error if the job is not actually concluded.
|
||||
*
|
||||
* Called with job lock held.
|
||||
*/
|
||||
void job_dismiss_locked(Job **job, Error **errp);
|
||||
|
||||
/**
|
||||
* Synchronously finishes the given @job. If @finish is given, it is called to
|
||||
* trigger completion or cancellation of the job.
|
||||
*
|
||||
* Returns 0 if the job is successfully completed, -ECANCELED if the job was
|
||||
* cancelled before completing, and -errno in other error cases.
|
||||
*
|
||||
* Called with job_lock held, but might release it temporarily.
|
||||
*/
|
||||
int job_finish_sync_locked(Job *job, void (*finish)(Job *, Error **errp),
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* Sets the @job->aio_context.
|
||||
* Called with job_mutex *not* held.
|
||||
*
|
||||
* This function must run in the main thread to protect against
|
||||
* concurrent read in job_finish_sync_locked(), takes the job_mutex
|
||||
* lock to protect against the read in job_do_yield_locked(), and must
|
||||
* be called when the job is quiescent.
|
||||
*/
|
||||
void job_set_aio_context(Job *job, AioContext *ctx);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 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 KEYVAL_H
|
||||
#define KEYVAL_H
|
||||
|
||||
QDict *keyval_parse_into(QDict *qdict, const char *params, const char *implied_key,
|
||||
bool *p_help, Error **errp);
|
||||
QDict *keyval_parse(const char *params, const char *implied_key,
|
||||
bool *help, Error **errp);
|
||||
void keyval_merge(QDict *old, const QDict *new, Error **errp);
|
||||
|
||||
#endif /* KEYVAL_H */
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Polymorphic locking functions (aka poor man templates)
|
||||
*
|
||||
* Copyright Red Hat, Inc. 2017, 2018
|
||||
*
|
||||
* Author: Paolo Bonzini <[email protected]>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QEMU_LOCKABLE_H
|
||||
#define QEMU_LOCKABLE_H
|
||||
|
||||
#include "qemu/coroutine-core.h"
|
||||
#include "qemu/thread.h"
|
||||
|
||||
typedef void QemuLockUnlockFunc(void *);
|
||||
|
||||
typedef struct QemuLockable {
|
||||
void *object;
|
||||
QemuLockUnlockFunc *lock;
|
||||
QemuLockUnlockFunc *unlock;
|
||||
} QemuLockable;
|
||||
|
||||
static inline __attribute__((__always_inline__)) QemuLockable *
|
||||
qemu_make_lockable(void *x, QemuLockable *lockable)
|
||||
{
|
||||
/*
|
||||
* We cannot test this in a macro, otherwise we get compiler
|
||||
* warnings like "the address of 'm' will always evaluate as 'true'".
|
||||
*/
|
||||
return x ? lockable : NULL;
|
||||
}
|
||||
|
||||
static inline __attribute__((__always_inline__)) QemuLockable *
|
||||
qemu_null_lockable(void *x)
|
||||
{
|
||||
if (x != NULL) {
|
||||
qemu_build_not_reached();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define QML_FUNC_(name) \
|
||||
static inline void qemu_lockable_ ## name ## _lock(void *x) \
|
||||
{ \
|
||||
qemu_ ## name ## _lock(x); \
|
||||
} \
|
||||
static inline void qemu_lockable_ ## name ## _unlock(void *x) \
|
||||
{ \
|
||||
qemu_ ## name ## _unlock(x); \
|
||||
}
|
||||
|
||||
QML_FUNC_(mutex)
|
||||
QML_FUNC_(rec_mutex)
|
||||
QML_FUNC_(co_mutex)
|
||||
QML_FUNC_(spin)
|
||||
|
||||
/*
|
||||
* In C, compound literals have the lifetime of an automatic variable.
|
||||
* In C++ it would be different, but then C++ wouldn't need QemuLockable
|
||||
* either...
|
||||
*/
|
||||
#define QML_OBJ_(x, name) (&(QemuLockable) { \
|
||||
.object = (x), \
|
||||
.lock = qemu_lockable_ ## name ## _lock, \
|
||||
.unlock = qemu_lockable_ ## name ## _unlock \
|
||||
})
|
||||
|
||||
/**
|
||||
* QEMU_MAKE_LOCKABLE - Make a polymorphic QemuLockable
|
||||
*
|
||||
* @x: a lock object (currently one of QemuMutex, QemuRecMutex,
|
||||
* CoMutex, QemuSpin).
|
||||
*
|
||||
* Returns a QemuLockable object that can be passed around
|
||||
* to a function that can operate with locks of any kind, or
|
||||
* NULL if @x is %NULL.
|
||||
*
|
||||
* Note the special case for void *, so that we may pass "NULL".
|
||||
*/
|
||||
#define QEMU_MAKE_LOCKABLE(x) \
|
||||
_Generic((x), QemuLockable *: (x), \
|
||||
void *: qemu_null_lockable(x), \
|
||||
QemuMutex *: qemu_make_lockable(x, QML_OBJ_(x, mutex)), \
|
||||
QemuRecMutex *: qemu_make_lockable(x, QML_OBJ_(x, rec_mutex)), \
|
||||
CoMutex *: qemu_make_lockable(x, QML_OBJ_(x, co_mutex)), \
|
||||
QemuSpin *: qemu_make_lockable(x, QML_OBJ_(x, spin)))
|
||||
|
||||
/**
|
||||
* QEMU_MAKE_LOCKABLE_NONNULL - Make a polymorphic QemuLockable
|
||||
*
|
||||
* @x: a lock object (currently one of QemuMutex, QemuRecMutex,
|
||||
* CoMutex, QemuSpin).
|
||||
*
|
||||
* Returns a QemuLockable object that can be passed around
|
||||
* to a function that can operate with locks of any kind.
|
||||
*/
|
||||
#define QEMU_MAKE_LOCKABLE_NONNULL(x) \
|
||||
_Generic((x), QemuLockable *: (x), \
|
||||
QemuMutex *: QML_OBJ_(x, mutex), \
|
||||
QemuRecMutex *: QML_OBJ_(x, rec_mutex), \
|
||||
CoMutex *: QML_OBJ_(x, co_mutex), \
|
||||
QemuSpin *: QML_OBJ_(x, spin))
|
||||
|
||||
static inline void qemu_lockable_lock(QemuLockable *x)
|
||||
{
|
||||
x->lock(x->object);
|
||||
}
|
||||
|
||||
static inline void qemu_lockable_unlock(QemuLockable *x)
|
||||
{
|
||||
x->unlock(x->object);
|
||||
}
|
||||
|
||||
static inline QemuLockable *qemu_lockable_auto_lock(QemuLockable *x)
|
||||
{
|
||||
qemu_lockable_lock(x);
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void qemu_lockable_auto_unlock(QemuLockable *x)
|
||||
{
|
||||
if (x) {
|
||||
qemu_lockable_unlock(x);
|
||||
}
|
||||
}
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(QemuLockable, qemu_lockable_auto_unlock)
|
||||
|
||||
#define WITH_QEMU_LOCK_GUARD_(x, var) \
|
||||
for (g_autoptr(QemuLockable) var = \
|
||||
qemu_lockable_auto_lock(QEMU_MAKE_LOCKABLE_NONNULL((x))); \
|
||||
var; \
|
||||
qemu_lockable_auto_unlock(var), var = NULL)
|
||||
|
||||
/**
|
||||
* WITH_QEMU_LOCK_GUARD - Lock a lock object for scope
|
||||
*
|
||||
* @x: a lock object (currently one of QemuMutex, CoMutex, QemuSpin).
|
||||
*
|
||||
* This macro defines a lock scope such that entering the scope takes the lock
|
||||
* and leaving the scope releases the lock. Return statements are allowed
|
||||
* within the scope and release the lock. Break and continue statements leave
|
||||
* the scope early and release the lock.
|
||||
*
|
||||
* WITH_QEMU_LOCK_GUARD(&mutex) {
|
||||
* ...
|
||||
* if (error) {
|
||||
* return; <-- mutex is automatically unlocked
|
||||
* }
|
||||
*
|
||||
* if (early_exit) {
|
||||
* break; <-- leave this scope early
|
||||
* }
|
||||
* ...
|
||||
* }
|
||||
*/
|
||||
#define WITH_QEMU_LOCK_GUARD(x) \
|
||||
WITH_QEMU_LOCK_GUARD_((x), glue(qemu_lockable_auto, __COUNTER__))
|
||||
|
||||
/**
|
||||
* QEMU_LOCK_GUARD - Lock an object until the end of the scope
|
||||
*
|
||||
* @x: a lock object (currently one of QemuMutex, CoMutex, QemuSpin).
|
||||
*
|
||||
* This macro takes a lock until the end of the scope. Return statements
|
||||
* release the lock.
|
||||
*
|
||||
* ... <-- mutex not locked
|
||||
* QEMU_LOCK_GUARD(&mutex); <-- mutex locked from here onwards
|
||||
* ...
|
||||
* if (error) {
|
||||
* return; <-- mutex is automatically unlocked
|
||||
* }
|
||||
*/
|
||||
#define QEMU_LOCK_GUARD(x) \
|
||||
g_autoptr(QemuLockable) \
|
||||
glue(qemu_lockable_auto, __COUNTER__) G_GNUC_UNUSED = \
|
||||
qemu_lockable_auto_lock(QEMU_MAKE_LOCKABLE((x)))
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,130 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* QemuLockCnt implementation
|
||||
*
|
||||
* Copyright Red Hat, Inc. 2017
|
||||
*
|
||||
* Author:
|
||||
* Paolo Bonzini <[email protected]>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QEMU_LOCKCNT_H
|
||||
#define QEMU_LOCKCNT_H
|
||||
|
||||
#include "qemu/thread.h"
|
||||
|
||||
typedef struct QemuLockCnt QemuLockCnt;
|
||||
|
||||
struct QemuLockCnt {
|
||||
#ifndef HAVE_FUTEX
|
||||
QemuMutex mutex;
|
||||
#endif
|
||||
unsigned count;
|
||||
};
|
||||
|
||||
/**
|
||||
* qemu_lockcnt_init: initialize a QemuLockcnt
|
||||
* @lockcnt: the lockcnt to initialize
|
||||
*
|
||||
* Initialize lockcnt's counter to zero and prepare its mutex
|
||||
* for usage.
|
||||
*/
|
||||
void qemu_lockcnt_init(QemuLockCnt *lockcnt);
|
||||
|
||||
/**
|
||||
* qemu_lockcnt_destroy: destroy a QemuLockcnt
|
||||
* @lockcnt: the lockcnt to destruct
|
||||
*
|
||||
* Destroy lockcnt's mutex.
|
||||
*/
|
||||
void qemu_lockcnt_destroy(QemuLockCnt *lockcnt);
|
||||
|
||||
/**
|
||||
* qemu_lockcnt_inc: increment a QemuLockCnt's counter
|
||||
* @lockcnt: the lockcnt to operate on
|
||||
*
|
||||
* If the lockcnt's count is zero, wait for critical sections
|
||||
* to finish and increment lockcnt's count to 1. If the count
|
||||
* is not zero, just increment it.
|
||||
*
|
||||
* Because this function can wait on the mutex, it must not be
|
||||
* called while the lockcnt's mutex is held by the current thread.
|
||||
* For the same reason, qemu_lockcnt_inc can also contribute to
|
||||
* AB-BA deadlocks. This is a sample deadlock scenario::
|
||||
*
|
||||
* thread 1 thread 2
|
||||
* -------------------------------------------------------
|
||||
* qemu_lockcnt_lock(&lc1);
|
||||
* qemu_lockcnt_lock(&lc2);
|
||||
* qemu_lockcnt_inc(&lc2);
|
||||
* qemu_lockcnt_inc(&lc1);
|
||||
*/
|
||||
void qemu_lockcnt_inc(QemuLockCnt *lockcnt);
|
||||
|
||||
/**
|
||||
* qemu_lockcnt_dec: decrement a QemuLockCnt's counter
|
||||
* @lockcnt: the lockcnt to operate on
|
||||
*/
|
||||
void qemu_lockcnt_dec(QemuLockCnt *lockcnt);
|
||||
|
||||
/**
|
||||
* qemu_lockcnt_dec_and_lock: decrement a QemuLockCnt's counter and
|
||||
* possibly lock it.
|
||||
* @lockcnt: the lockcnt to operate on
|
||||
*
|
||||
* Decrement lockcnt's count. If the new count is zero, lock
|
||||
* the mutex and return true. Otherwise, return false.
|
||||
*/
|
||||
bool qemu_lockcnt_dec_and_lock(QemuLockCnt *lockcnt);
|
||||
|
||||
/**
|
||||
* qemu_lockcnt_dec_if_lock: possibly decrement a QemuLockCnt's counter and
|
||||
* lock it.
|
||||
* @lockcnt: the lockcnt to operate on
|
||||
*
|
||||
* If the count is 1, decrement the count to zero, lock
|
||||
* the mutex and return true. Otherwise, return false.
|
||||
*/
|
||||
bool qemu_lockcnt_dec_if_lock(QemuLockCnt *lockcnt);
|
||||
|
||||
/**
|
||||
* qemu_lockcnt_lock: lock a QemuLockCnt's mutex.
|
||||
* @lockcnt: the lockcnt to operate on
|
||||
*
|
||||
* Remember that concurrent visits are not blocked unless the count is
|
||||
* also zero. You can use qemu_lockcnt_count to check for this inside a
|
||||
* critical section.
|
||||
*/
|
||||
void qemu_lockcnt_lock(QemuLockCnt *lockcnt);
|
||||
|
||||
/**
|
||||
* qemu_lockcnt_unlock: release a QemuLockCnt's mutex.
|
||||
* @lockcnt: the lockcnt to operate on.
|
||||
*/
|
||||
void qemu_lockcnt_unlock(QemuLockCnt *lockcnt);
|
||||
|
||||
/**
|
||||
* qemu_lockcnt_inc_and_unlock: combined unlock/increment on a QemuLockCnt.
|
||||
* @lockcnt: the lockcnt to operate on.
|
||||
*
|
||||
* This is the same as
|
||||
*
|
||||
* qemu_lockcnt_unlock(lockcnt);
|
||||
* qemu_lockcnt_inc(lockcnt);
|
||||
*
|
||||
* but more efficient.
|
||||
*/
|
||||
void qemu_lockcnt_inc_and_unlock(QemuLockCnt *lockcnt);
|
||||
|
||||
/**
|
||||
* qemu_lockcnt_count: query a LockCnt's count.
|
||||
* @lockcnt: the lockcnt to query.
|
||||
*
|
||||
* Note that the count can change at any time. Still, while the
|
||||
* lockcnt is locked, one can usefully check whether the count
|
||||
* is non-zero.
|
||||
*/
|
||||
unsigned qemu_lockcnt_count(QemuLockCnt *lockcnt);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,50 @@
|
||||
/* log-for-trace.h: logging basics required by the trace.h generated
|
||||
* by the log trace backend.
|
||||
*
|
||||
* This should not be included directly by any .c file: if you
|
||||
* need to use the logging functions include "qemu/log.h".
|
||||
*
|
||||
* The purpose of splitting these parts out into their own header
|
||||
* is to catch the easy mistake where a .c file includes trace.h
|
||||
* but forgets to include qemu/log.h. Without this split, that
|
||||
* would result in the .c file compiling fine when the default
|
||||
* trace backend is in use but failing to compile with any other
|
||||
* backend.
|
||||
*
|
||||
* This code is licensed under the GNU General Public License,
|
||||
* version 2 or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_LOG_FOR_TRACE_H
|
||||
#define QEMU_LOG_FOR_TRACE_H
|
||||
|
||||
/* Private global variable, don't use */
|
||||
extern unsigned qemu_loglevel;
|
||||
|
||||
#define LOG_TRACE (1u << 15)
|
||||
|
||||
/* Returns true if a bit is set in the current loglevel mask */
|
||||
static inline bool qemu_loglevel_mask(int mask)
|
||||
{
|
||||
return (qemu_loglevel & mask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* qemu_log: report a log message
|
||||
* @fmt: the format string for the message
|
||||
* @...: the format string arguments
|
||||
*
|
||||
* This will emit a log message to the current output stream.
|
||||
*
|
||||
* The @fmt string should normally represent a complete line
|
||||
* of text, and thus end with a newline character.
|
||||
*
|
||||
* While it is possible to incrementally output fragments of
|
||||
* a complete line using qemu_log, this is inefficient and
|
||||
* races with other threads. For outputting fragments it is
|
||||
* strongly preferred to use the qemu_log_trylock() method
|
||||
* combined with fprintf().
|
||||
*/
|
||||
void G_GNUC_PRINTF(1, 2) qemu_log(const char *fmt, ...);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,140 @@
|
||||
#ifndef QEMU_LOG_H
|
||||
#define QEMU_LOG_H
|
||||
|
||||
/* A small part of this API is split into its own header */
|
||||
#include "qemu/log-for-trace.h"
|
||||
|
||||
/*
|
||||
* The new API:
|
||||
*/
|
||||
|
||||
/* Returns true if qemu_log() will really write somewhere. */
|
||||
bool qemu_log_enabled(void);
|
||||
|
||||
/* Returns true if qemu_log() will write somewhere other than stderr. */
|
||||
bool qemu_log_separate(void);
|
||||
|
||||
#define CPU_LOG_TB_OUT_ASM (1u << 0)
|
||||
#define CPU_LOG_TB_IN_ASM (1u << 1)
|
||||
#define CPU_LOG_TB_OP (1u << 2)
|
||||
#define CPU_LOG_TB_OP_OPT (1u << 3)
|
||||
#define CPU_LOG_INT (1u << 4)
|
||||
#define CPU_LOG_EXEC (1u << 5)
|
||||
#define CPU_LOG_PCALL (1u << 6)
|
||||
#define CPU_LOG_TB_CPU (1u << 8)
|
||||
#define CPU_LOG_RESET (1u << 9)
|
||||
#define LOG_UNIMP (1u << 10)
|
||||
#define LOG_GUEST_ERROR (1u << 11)
|
||||
#define CPU_LOG_MMU (1u << 12)
|
||||
#define CPU_LOG_TB_NOCHAIN (1u << 13)
|
||||
#define CPU_LOG_PAGE (1u << 14)
|
||||
/* LOG_TRACE (1 << 15) is defined in log-for-trace.h */
|
||||
#define CPU_LOG_TB_OP_IND (1u << 16)
|
||||
#define CPU_LOG_TB_FPU (1u << 17)
|
||||
#define CPU_LOG_PLUGIN (1u << 18)
|
||||
/* LOG_STRACE is used for user-mode strace logging. */
|
||||
#define LOG_STRACE (1u << 19)
|
||||
#define LOG_PER_THREAD (1u << 20)
|
||||
#define CPU_LOG_TB_VPU (1u << 21)
|
||||
#define LOG_TB_OP_PLUGIN (1u << 22)
|
||||
#define LOG_INVALID_MEM (1u << 23)
|
||||
|
||||
/* Lock/unlock output. */
|
||||
|
||||
/**
|
||||
* Acquires a lock on the current log output stream.
|
||||
* The returned FILE object should be used with the
|
||||
* fprintf() function to output the log message, and
|
||||
* then qemu_log_unlock() called to release the lock.
|
||||
*
|
||||
* The primary use case is to be able to incrementally
|
||||
* output fragments of a complete log message in an
|
||||
* efficient and race free manner.
|
||||
*
|
||||
* The simpler qemu_log() method should normally only
|
||||
* be used to output complete log messages, and not
|
||||
* within scope of a qemu_log_trylock() call.
|
||||
*
|
||||
* A typical usage pattern would be
|
||||
*
|
||||
* FILE *f = qemu_log_trylock()
|
||||
*
|
||||
* fprintf(f, "Something ");
|
||||
* fprintf(f, "Something ");
|
||||
* fprintf(f, "Something ");
|
||||
* fprintf(f, "The end\n");
|
||||
*
|
||||
* qemu_log_unlock(f);
|
||||
*
|
||||
* Returns: the current FILE if available, NULL on error
|
||||
*/
|
||||
FILE *qemu_log_trylock(void) G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
/**
|
||||
* As qemu_log_trylock(), but will also print the message
|
||||
* context, if any is configured and this caused the
|
||||
* acquisition of the FILE lock
|
||||
*/
|
||||
FILE *qemu_log_trylock_with_context(void) G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
/**
|
||||
* Releases the lock on the log output, previously
|
||||
* acquired by qemu_log_trylock().
|
||||
*/
|
||||
void qemu_log_unlock(FILE *fd);
|
||||
|
||||
/* Logging functions: */
|
||||
|
||||
/* log only if a bit is set on the current loglevel mask:
|
||||
* @mask: bit to check in the mask
|
||||
* @fmt: printf-style format string
|
||||
* @args: optional arguments for format string
|
||||
*/
|
||||
#define qemu_log_mask(MASK, FMT, ...) \
|
||||
do { \
|
||||
if (unlikely(qemu_loglevel_mask(MASK))) { \
|
||||
qemu_log(FMT, ## __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* log only if a bit is set on the current loglevel mask
|
||||
* and we are in the address range we care about:
|
||||
* @mask: bit to check in the mask
|
||||
* @addr: address to check in dfilter
|
||||
* @fmt: printf-style format string
|
||||
* @args: optional arguments for format string
|
||||
*/
|
||||
#define qemu_log_mask_and_addr(MASK, ADDR, FMT, ...) \
|
||||
do { \
|
||||
if (unlikely(qemu_loglevel_mask(MASK)) && \
|
||||
qemu_log_in_addr_range(ADDR)) { \
|
||||
qemu_log(FMT, ## __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Maintenance: */
|
||||
|
||||
/* define log items */
|
||||
typedef struct QEMULogItem {
|
||||
int mask;
|
||||
const char *name;
|
||||
const char *help;
|
||||
} QEMULogItem;
|
||||
|
||||
extern const QEMULogItem qemu_log_items[];
|
||||
|
||||
ssize_t rust_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
|
||||
|
||||
bool qemu_set_log(int log_flags, Error **errp);
|
||||
bool qemu_set_log_filename(const char *filename, Error **errp);
|
||||
bool qemu_set_log_filename_flags(const char *name, int flags, Error **errp);
|
||||
void qemu_set_dfilter_ranges(const char *ranges, Error **errp);
|
||||
bool qemu_log_in_addr_range(uint64_t addr);
|
||||
int qemu_str_to_log_mask(const char *str);
|
||||
|
||||
/* Print a usage message listing all the valid logging categories
|
||||
* to the specified FILE*.
|
||||
*/
|
||||
void qemu_print_log_usage(FILE *f);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* QEMU madvise wrapper functions
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_MADVISE_H
|
||||
#define QEMU_MADVISE_H
|
||||
|
||||
#define QEMU_MADV_INVALID -1
|
||||
|
||||
#if defined(CONFIG_MADVISE)
|
||||
|
||||
#define QEMU_MADV_WILLNEED MADV_WILLNEED
|
||||
#define QEMU_MADV_DONTNEED MADV_DONTNEED
|
||||
#ifdef MADV_DONTFORK
|
||||
#define QEMU_MADV_DONTFORK MADV_DONTFORK
|
||||
#else
|
||||
#define QEMU_MADV_DONTFORK QEMU_MADV_INVALID
|
||||
#endif
|
||||
#ifdef MADV_MERGEABLE
|
||||
#define QEMU_MADV_MERGEABLE MADV_MERGEABLE
|
||||
#else
|
||||
#define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID
|
||||
#endif
|
||||
#ifdef MADV_UNMERGEABLE
|
||||
#define QEMU_MADV_UNMERGEABLE MADV_UNMERGEABLE
|
||||
#else
|
||||
#define QEMU_MADV_UNMERGEABLE QEMU_MADV_INVALID
|
||||
#endif
|
||||
#ifdef MADV_DODUMP
|
||||
#define QEMU_MADV_DODUMP MADV_DODUMP
|
||||
#else
|
||||
#define QEMU_MADV_DODUMP QEMU_MADV_INVALID
|
||||
#endif
|
||||
#ifdef MADV_DONTDUMP
|
||||
#define QEMU_MADV_DONTDUMP MADV_DONTDUMP
|
||||
#else
|
||||
#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID
|
||||
#endif
|
||||
#ifdef MADV_HUGEPAGE
|
||||
#define QEMU_MADV_HUGEPAGE MADV_HUGEPAGE
|
||||
#else
|
||||
#define QEMU_MADV_HUGEPAGE QEMU_MADV_INVALID
|
||||
#endif
|
||||
#ifdef MADV_NOHUGEPAGE
|
||||
#define QEMU_MADV_NOHUGEPAGE MADV_NOHUGEPAGE
|
||||
#else
|
||||
#define QEMU_MADV_NOHUGEPAGE QEMU_MADV_INVALID
|
||||
#endif
|
||||
#ifdef MADV_REMOVE
|
||||
#define QEMU_MADV_REMOVE MADV_REMOVE
|
||||
#else
|
||||
#define QEMU_MADV_REMOVE QEMU_MADV_DONTNEED
|
||||
#endif
|
||||
#ifdef MADV_POPULATE_WRITE
|
||||
#define QEMU_MADV_POPULATE_WRITE MADV_POPULATE_WRITE
|
||||
#else
|
||||
#define QEMU_MADV_POPULATE_WRITE QEMU_MADV_INVALID
|
||||
#endif
|
||||
|
||||
#elif defined(CONFIG_POSIX_MADVISE)
|
||||
|
||||
#define QEMU_MADV_WILLNEED POSIX_MADV_WILLNEED
|
||||
#define QEMU_MADV_DONTNEED POSIX_MADV_DONTNEED
|
||||
#define QEMU_MADV_DONTFORK QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_UNMERGEABLE QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_DODUMP QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_HUGEPAGE QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_NOHUGEPAGE QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_REMOVE QEMU_MADV_DONTNEED
|
||||
#define QEMU_MADV_POPULATE_WRITE QEMU_MADV_INVALID
|
||||
|
||||
#else /* no-op */
|
||||
|
||||
#define QEMU_MADV_WILLNEED QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_DONTNEED QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_DONTFORK QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_UNMERGEABLE QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_DODUMP QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_HUGEPAGE QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_NOHUGEPAGE QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_REMOVE QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_POPULATE_WRITE QEMU_MADV_INVALID
|
||||
|
||||
#endif
|
||||
|
||||
int qemu_madvise(void *addr, size_t len, int advice);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,452 @@
|
||||
/*
|
||||
* QEMU System Emulator
|
||||
*
|
||||
* Copyright (c) 2003-2008 Fabrice Bellard
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_MAIN_LOOP_H
|
||||
#define QEMU_MAIN_LOOP_H
|
||||
|
||||
#include "qemu/aio.h"
|
||||
#include "qom/object.h"
|
||||
#include "system/event-loop-base.h"
|
||||
|
||||
#define SIG_IPI SIGUSR1
|
||||
|
||||
#define TYPE_MAIN_LOOP "main-loop"
|
||||
OBJECT_DECLARE_TYPE(MainLoop, MainLoopClass, MAIN_LOOP)
|
||||
|
||||
struct MainLoop {
|
||||
EventLoopBase parent_obj;
|
||||
};
|
||||
typedef struct MainLoop MainLoop;
|
||||
|
||||
/**
|
||||
* qemu_init_main_loop: Set up the process so that it can run the main loop.
|
||||
*
|
||||
* This includes setting up signal handlers. It should be called before
|
||||
* any other threads are created. In addition, threads other than the
|
||||
* main one should block signals that are trapped by the main loop.
|
||||
* For simplicity, you can consider these signals to be safe: SIGUSR1,
|
||||
* SIGUSR2, thread signals (SIGFPE, SIGILL, SIGSEGV, SIGBUS) and real-time
|
||||
* signals if available. Remember that Windows in practice does not have
|
||||
* signals, though.
|
||||
*
|
||||
* In the case of QEMU tools, this will also start/initialize timers.
|
||||
*/
|
||||
int qemu_init_main_loop(Error **errp);
|
||||
|
||||
/**
|
||||
* main_loop_wait: Run one iteration of the main loop.
|
||||
*
|
||||
* If @nonblocking is true, poll for events, otherwise suspend until
|
||||
* one actually occurs. The main loop usually consists of a loop that
|
||||
* repeatedly calls main_loop_wait(false).
|
||||
*
|
||||
* Main loop services include file descriptor callbacks, bottom halves
|
||||
* and timers (defined in qemu/timer.h). Bottom halves are similar to timers
|
||||
* that execute immediately, but have a lower overhead and scheduling them
|
||||
* is wait-free, thread-safe and signal-safe.
|
||||
*
|
||||
* It is sometimes useful to put a whole program in a coroutine. In this
|
||||
* case, the coroutine actually should be started from within the main loop,
|
||||
* so that the main loop can run whenever the coroutine yields. To do this,
|
||||
* you can use a bottom half to enter the coroutine as soon as the main loop
|
||||
* starts:
|
||||
*
|
||||
* void enter_co_bh(void *opaque) {
|
||||
* QEMUCoroutine *co = opaque;
|
||||
* qemu_coroutine_enter(co);
|
||||
* }
|
||||
*
|
||||
* ...
|
||||
* QEMUCoroutine *co = qemu_coroutine_create(coroutine_entry, NULL);
|
||||
* QEMUBH *start_bh = qemu_bh_new(enter_co_bh, co);
|
||||
* qemu_bh_schedule(start_bh);
|
||||
* while (...) {
|
||||
* main_loop_wait(false);
|
||||
* }
|
||||
*
|
||||
* (In the future we may provide a wrapper for this).
|
||||
*
|
||||
* @nonblocking: Whether the caller should block until an event occurs.
|
||||
*/
|
||||
void main_loop_wait(int nonblocking);
|
||||
|
||||
/**
|
||||
* qemu_get_aio_context: Return the main loop's AioContext
|
||||
*/
|
||||
AioContext *qemu_get_aio_context(void);
|
||||
|
||||
/**
|
||||
* qemu_notify_event: Force processing of pending events.
|
||||
*
|
||||
* Similar to signaling a condition variable, qemu_notify_event forces
|
||||
* main_loop_wait to look at pending events and exit. The caller of
|
||||
* main_loop_wait will usually call it again very soon, so qemu_notify_event
|
||||
* also has the side effect of recalculating the sets of file descriptors
|
||||
* that the main loop waits for.
|
||||
*
|
||||
* Calling qemu_notify_event is rarely necessary, because main loop
|
||||
* services (bottom halves and timers) call it themselves.
|
||||
*/
|
||||
void qemu_notify_event(void);
|
||||
|
||||
#ifdef _WIN32
|
||||
/* return TRUE if no sleep should be done afterwards */
|
||||
typedef int PollingFunc(void *opaque);
|
||||
|
||||
/**
|
||||
* qemu_add_polling_cb: Register a Windows-specific polling callback
|
||||
*
|
||||
* Currently, under Windows some events are polled rather than waited for.
|
||||
* Polling callbacks do not ensure that @func is called timely, because
|
||||
* the main loop might wait for an arbitrarily long time. If possible,
|
||||
* you should instead create a separate thread that does a blocking poll
|
||||
* and set a Win32 event object. The event can then be passed to
|
||||
* qemu_add_wait_object.
|
||||
*
|
||||
* Polling callbacks really have nothing Windows specific in them, but
|
||||
* as they are a hack and are currently not necessary under POSIX systems,
|
||||
* they are only available when QEMU is running under Windows.
|
||||
*
|
||||
* @func: The function that does the polling, and returns 1 to force
|
||||
* immediate completion of main_loop_wait.
|
||||
* @opaque: A pointer-size value that is passed to @func.
|
||||
*/
|
||||
int qemu_add_polling_cb(PollingFunc *func, void *opaque);
|
||||
|
||||
/**
|
||||
* qemu_del_polling_cb: Unregister a Windows-specific polling callback
|
||||
*
|
||||
* This function removes a callback that was registered with
|
||||
* qemu_add_polling_cb.
|
||||
*
|
||||
* @func: The function that was passed to qemu_add_polling_cb.
|
||||
* @opaque: A pointer-size value that was passed to qemu_add_polling_cb.
|
||||
*/
|
||||
void qemu_del_polling_cb(PollingFunc *func, void *opaque);
|
||||
|
||||
/* Wait objects handling */
|
||||
typedef void WaitObjectFunc(void *opaque);
|
||||
|
||||
/**
|
||||
* qemu_add_wait_object: Register a callback for a Windows handle
|
||||
*
|
||||
* Under Windows, the iohandler mechanism can only be used with sockets.
|
||||
* QEMU must use the WaitForMultipleObjects API to wait on other handles.
|
||||
* This function registers a #HANDLE with QEMU, so that it will be included
|
||||
* in the main loop's calls to WaitForMultipleObjects. When the handle
|
||||
* is in a signaled state, QEMU will call @func.
|
||||
*
|
||||
* If the same HANDLE is added twice, this function returns -1.
|
||||
*
|
||||
* @handle: The Windows handle to be observed.
|
||||
* @func: A function to be called when @handle is in a signaled state.
|
||||
* @opaque: A pointer-size value that is passed to @func.
|
||||
*/
|
||||
int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
|
||||
|
||||
/**
|
||||
* qemu_del_wait_object: Unregister a callback for a Windows handle
|
||||
*
|
||||
* This function removes a callback that was registered with
|
||||
* qemu_add_wait_object.
|
||||
*
|
||||
* @func: The function that was passed to qemu_add_wait_object.
|
||||
* @opaque: A pointer-size value that was passed to qemu_add_wait_object.
|
||||
*/
|
||||
void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
|
||||
#endif
|
||||
|
||||
/* async I/O support */
|
||||
|
||||
typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size);
|
||||
|
||||
/**
|
||||
* IOCanReadHandler: Return the number of bytes that #IOReadHandler can accept
|
||||
*
|
||||
* This function reports how many bytes #IOReadHandler is prepared to accept.
|
||||
* #IOReadHandler may be invoked with up to this number of bytes. If this
|
||||
* function returns 0 then #IOReadHandler is not invoked.
|
||||
*
|
||||
* This function is typically called from an event loop. If the number of
|
||||
* bytes changes outside the event loop (e.g. because a vcpu thread drained the
|
||||
* buffer), then it is necessary to kick the event loop so that this function
|
||||
* is called again. aio_notify() or qemu_notify_event() can be used to kick
|
||||
* the event loop.
|
||||
*/
|
||||
typedef int IOCanReadHandler(void *opaque);
|
||||
|
||||
/**
|
||||
* qemu_set_fd_handler: Register a file descriptor with the main loop
|
||||
*
|
||||
* This function tells the main loop to wake up whenever one of the
|
||||
* following conditions is true:
|
||||
*
|
||||
* 1) if @fd_write is not %NULL, when the file descriptor is writable;
|
||||
*
|
||||
* 2) if @fd_read is not %NULL, when the file descriptor is readable.
|
||||
*
|
||||
* The callbacks that are set up by qemu_set_fd_handler are level-triggered.
|
||||
* If @fd_read does not read from @fd, or @fd_write does not write to @fd
|
||||
* until its buffers are full, they will be called again on the next
|
||||
* iteration.
|
||||
*
|
||||
* @fd: The file descriptor to be observed. Under Windows it must be
|
||||
* a #SOCKET.
|
||||
*
|
||||
* @fd_read: A level-triggered callback that is fired if @fd is readable
|
||||
* at the beginning of a main loop iteration, or if it becomes readable
|
||||
* during one.
|
||||
*
|
||||
* @fd_write: A level-triggered callback that is fired when @fd is writable
|
||||
* at the beginning of a main loop iteration, or if it becomes writable
|
||||
* during one.
|
||||
*
|
||||
* @opaque: A pointer-sized value that is passed to @fd_read and @fd_write.
|
||||
*/
|
||||
void qemu_set_fd_handler(int fd,
|
||||
IOHandler *fd_read,
|
||||
IOHandler *fd_write,
|
||||
void *opaque);
|
||||
|
||||
|
||||
/**
|
||||
* event_notifier_set_handler: Register an EventNotifier with the main loop
|
||||
*
|
||||
* This function tells the main loop to wake up whenever the
|
||||
* #EventNotifier was set.
|
||||
*
|
||||
* @e: The #EventNotifier to be observed.
|
||||
*
|
||||
* @handler: A level-triggered callback that is fired when @e
|
||||
* has been set. @e is passed to it as a parameter.
|
||||
*/
|
||||
void event_notifier_set_handler(EventNotifier *e,
|
||||
EventNotifierHandler *handler);
|
||||
|
||||
GSource *iohandler_get_g_source(void);
|
||||
AioContext *iohandler_get_aio_context(void);
|
||||
|
||||
/**
|
||||
* rust_bql_mock_lock:
|
||||
*
|
||||
* Called from Rust doctests to make bql_lock() return true.
|
||||
* Do not touch.
|
||||
*/
|
||||
void rust_bql_mock_lock(void);
|
||||
|
||||
/**
|
||||
* bql_locked: Return lock status of the Big QEMU Lock (BQL)
|
||||
*
|
||||
* The Big QEMU Lock (BQL) is the coarsest lock in QEMU, and as such it
|
||||
* must always be taken outside other locks. This function helps
|
||||
* functions take different paths depending on whether the current
|
||||
* thread is running within the BQL.
|
||||
*
|
||||
* This function should never be used in the block layer, because
|
||||
* unit tests, block layer tools and qemu-storage-daemon do not
|
||||
* have a BQL.
|
||||
* Please instead refer to qemu_in_main_thread().
|
||||
*/
|
||||
bool bql_locked(void);
|
||||
|
||||
/**
|
||||
* mutex_is_bql:
|
||||
*
|
||||
* @mutex: the mutex pointer
|
||||
*
|
||||
* Returns whether the mutex is the BQL.
|
||||
*/
|
||||
bool mutex_is_bql(QemuMutex *mutex);
|
||||
|
||||
/**
|
||||
* bql_update_status:
|
||||
*
|
||||
* @locked: update status on whether the BQL is locked
|
||||
*
|
||||
* NOTE: this should normally only be invoked when the status changed.
|
||||
*/
|
||||
void bql_update_status(bool locked);
|
||||
|
||||
/**
|
||||
* bql_block: Allow/deny releasing the BQL
|
||||
*
|
||||
* The Big QEMU Lock (BQL) is used to provide interior mutability to
|
||||
* Rust code, but this only works if other threads cannot run while
|
||||
* the Rust code has an active borrow. This is because C code in
|
||||
* other threads could come in and mutate data under the Rust code's
|
||||
* feet.
|
||||
*
|
||||
* @increase: Whether to increase or decrease the blocking counter.
|
||||
* Releasing the BQL while the counter is nonzero triggers
|
||||
* an assertion failure.
|
||||
*/
|
||||
void bql_block_unlock(bool increase);
|
||||
|
||||
/**
|
||||
* qemu_in_main_thread: return whether it's possible to safely access
|
||||
* the global state of the block layer.
|
||||
*
|
||||
* Global state of the block layer is not accessible from I/O threads
|
||||
* or worker threads; only from threads that "own" the default
|
||||
* AioContext that qemu_get_aio_context() returns. For tests, block
|
||||
* layer tools and qemu-storage-daemon there is a designated thread that
|
||||
* runs the event loop for qemu_get_aio_context(), and that is the
|
||||
* main thread.
|
||||
*
|
||||
* For emulators, however, any thread that holds the BQL can act
|
||||
* as the block layer main thread; this will be any of the actual
|
||||
* main thread, the vCPU threads or the RCU thread.
|
||||
*
|
||||
* For clarity, do not use this function outside the block layer.
|
||||
*/
|
||||
bool qemu_in_main_thread(void);
|
||||
|
||||
/*
|
||||
* Mark and check that the function is part of the Global State API.
|
||||
* Please refer to include/block/block-global-state.h for more
|
||||
* information about GS API.
|
||||
*/
|
||||
#define GLOBAL_STATE_CODE() \
|
||||
do { \
|
||||
assert(qemu_in_main_thread()); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Mark and check that the function is part of the I/O API.
|
||||
* Please refer to include/block/block-io.h for more
|
||||
* information about IO API.
|
||||
*/
|
||||
#define IO_CODE() \
|
||||
do { \
|
||||
/* nop */ \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Mark and check that the function is part of the "I/O OR GS" API.
|
||||
* Please refer to include/block/block-io.h for more
|
||||
* information about "IO or GS" API.
|
||||
*/
|
||||
#define IO_OR_GS_CODE() \
|
||||
do { \
|
||||
/* nop */ \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* bql_lock: Lock the Big QEMU Lock (BQL).
|
||||
*
|
||||
* This function locks the Big QEMU Lock (BQL). The lock is taken by
|
||||
* main() in vl.c and always taken except while waiting on
|
||||
* external events (such as with select). The lock should be taken
|
||||
* by threads other than the main loop thread when calling
|
||||
* qemu_bh_new(), qemu_set_fd_handler() and basically all other
|
||||
* functions documented in this file.
|
||||
*
|
||||
* NOTE: tools currently are single-threaded and bql_lock
|
||||
* is a no-op there.
|
||||
*/
|
||||
#define bql_lock() bql_lock_impl(__FILE__, __LINE__)
|
||||
void bql_lock_impl(const char *file, int line);
|
||||
|
||||
/**
|
||||
* bql_unlock: Unlock the Big QEMU Lock (BQL).
|
||||
*
|
||||
* This function unlocks the Big QEMU Lock. The lock is taken by
|
||||
* main() in vl.c and always taken except while waiting on
|
||||
* external events (such as with select). The lock should be unlocked
|
||||
* as soon as possible by threads other than the main loop thread,
|
||||
* because it prevents the main loop from processing callbacks,
|
||||
* including timers and bottom halves.
|
||||
*
|
||||
* NOTE: tools currently are single-threaded and bql_unlock
|
||||
* is a no-op there.
|
||||
*/
|
||||
void bql_unlock(void);
|
||||
|
||||
/**
|
||||
* BQL_LOCK_GUARD
|
||||
*
|
||||
* Wrap a block of code in a conditional bql_{lock,unlock}.
|
||||
*/
|
||||
typedef struct BQLLockAuto BQLLockAuto;
|
||||
|
||||
static inline BQLLockAuto *bql_auto_lock(const char *file, int line)
|
||||
{
|
||||
if (bql_locked()) {
|
||||
return NULL;
|
||||
}
|
||||
bql_lock_impl(file, line);
|
||||
/* Anything non-NULL causes the cleanup function to be called */
|
||||
return (BQLLockAuto *)(uintptr_t)1;
|
||||
}
|
||||
|
||||
static inline void bql_auto_unlock(BQLLockAuto *l)
|
||||
{
|
||||
bql_unlock();
|
||||
}
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(BQLLockAuto, bql_auto_unlock)
|
||||
|
||||
#define BQL_LOCK_GUARD() \
|
||||
g_autoptr(BQLLockAuto) _bql_lock_auto __attribute__((unused)) \
|
||||
= bql_auto_lock(__FILE__, __LINE__)
|
||||
|
||||
/*
|
||||
* qemu_cond_wait_bql: Wait on condition for the Big QEMU Lock (BQL)
|
||||
*
|
||||
* This function atomically releases the Big QEMU Lock (BQL) and causes
|
||||
* the calling thread to block on the condition.
|
||||
*/
|
||||
void qemu_cond_wait_bql(QemuCond *cond);
|
||||
|
||||
/*
|
||||
* qemu_cond_timedwait_bql: like the previous, but with timeout
|
||||
*/
|
||||
void qemu_cond_timedwait_bql(QemuCond *cond, int ms);
|
||||
|
||||
/* internal interfaces */
|
||||
|
||||
#define qemu_bh_new_guarded(cb, opaque, guard) \
|
||||
qemu_bh_new_full((cb), (opaque), (stringify(cb)), guard)
|
||||
#define qemu_bh_new(cb, opaque) \
|
||||
qemu_bh_new_full((cb), (opaque), (stringify(cb)), NULL)
|
||||
QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name,
|
||||
struct MemReentrancyGuard *reentrancy_guard);
|
||||
void qemu_bh_schedule_idle(QEMUBH *bh);
|
||||
|
||||
enum {
|
||||
MAIN_LOOP_POLL_FILL,
|
||||
MAIN_LOOP_POLL_ERR,
|
||||
MAIN_LOOP_POLL_OK,
|
||||
};
|
||||
|
||||
typedef struct MainLoopPoll {
|
||||
int state;
|
||||
uint32_t timeout;
|
||||
GArray *pollfds;
|
||||
} MainLoopPoll;
|
||||
|
||||
void main_loop_poll_add_notifier(Notifier *notify);
|
||||
void main_loop_poll_remove_notifier(Notifier *notify);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,10 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#ifndef QEMU_MEM_REENTRANCY_H
|
||||
#define QEMU_MEM_REENTRANCY_H 1
|
||||
|
||||
typedef struct MemReentrancyGuard {
|
||||
bool engaged_in_io;
|
||||
} MemReentrancyGuard;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Allocation and free functions for aligned memory
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_MEMALIGN_H
|
||||
#define QEMU_MEMALIGN_H
|
||||
|
||||
/**
|
||||
* qemu_try_memalign: Allocate aligned memory
|
||||
* @alignment: required alignment, in bytes
|
||||
* @size: size of allocation, in bytes
|
||||
*
|
||||
* Allocate memory on an aligned boundary (i.e. the returned
|
||||
* address will be an exact multiple of @alignment).
|
||||
* @alignment must be a power of 2, or the function will assert().
|
||||
* On success, returns allocated memory; on failure, returns NULL.
|
||||
*
|
||||
* The memory allocated through this function must be freed via
|
||||
* qemu_vfree() (and not via free()).
|
||||
*/
|
||||
void *qemu_try_memalign(size_t alignment, size_t size);
|
||||
/**
|
||||
* qemu_memalign: Allocate aligned memory, without failing
|
||||
* @alignment: required alignment, in bytes
|
||||
* @size: size of allocation, in bytes
|
||||
*
|
||||
* Allocate memory in the same way as qemu_try_memalign(), but
|
||||
* abort() with an error message if the memory allocation fails.
|
||||
*
|
||||
* The memory allocated through this function must be freed via
|
||||
* qemu_vfree() (and not via free()).
|
||||
*/
|
||||
void *qemu_memalign(size_t alignment, size_t size);
|
||||
/**
|
||||
* qemu_vfree: Free memory allocated through qemu_memalign
|
||||
* @ptr: memory to free
|
||||
*
|
||||
* This function must be used to free memory allocated via qemu_memalign()
|
||||
* or qemu_try_memalign(). (Using the wrong free function will cause
|
||||
* subtle bugs on Windows hosts.)
|
||||
*/
|
||||
void qemu_vfree(void *ptr);
|
||||
/*
|
||||
* It's an analog of GLIB's g_autoptr_cleanup_generic_gfree(), used to define
|
||||
* g_autofree macro.
|
||||
*/
|
||||
static inline void qemu_cleanup_generic_vfree(void *p)
|
||||
{
|
||||
void **pp = (void **)p;
|
||||
qemu_vfree(*pp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Analog of g_autofree, but qemu_vfree is called on cleanup instead of g_free.
|
||||
*/
|
||||
#define QEMU_AUTO_VFREE __attribute__((cleanup(qemu_cleanup_generic_vfree)))
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,47 @@
|
||||
#ifndef QEMU_MEMFD_H
|
||||
#define QEMU_MEMFD_H
|
||||
|
||||
|
||||
#ifndef F_LINUX_SPECIFIC_BASE
|
||||
#define F_LINUX_SPECIFIC_BASE 1024
|
||||
#endif
|
||||
|
||||
#ifndef F_ADD_SEALS
|
||||
#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
|
||||
#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10)
|
||||
|
||||
#define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */
|
||||
#define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */
|
||||
#define F_SEAL_GROW 0x0004 /* prevent file from growing */
|
||||
#define F_SEAL_WRITE 0x0008 /* prevent writes */
|
||||
#endif
|
||||
|
||||
#ifndef MFD_CLOEXEC
|
||||
#define MFD_CLOEXEC 0x0001U
|
||||
#endif
|
||||
|
||||
#ifndef MFD_ALLOW_SEALING
|
||||
#define MFD_ALLOW_SEALING 0x0002U
|
||||
#endif
|
||||
|
||||
#ifndef MFD_HUGETLB
|
||||
#define MFD_HUGETLB 0x0004U
|
||||
#endif
|
||||
|
||||
#ifndef MFD_HUGE_SHIFT
|
||||
#define MFD_HUGE_SHIFT 26
|
||||
#endif
|
||||
|
||||
#if defined CONFIG_LINUX && !defined CONFIG_MEMFD
|
||||
int memfd_create(const char *name, unsigned int flags);
|
||||
#endif
|
||||
|
||||
int qemu_memfd_create(const char *name, size_t size, bool hugetlb,
|
||||
uint64_t hugetlbsize, unsigned int seals, Error **errp);
|
||||
bool qemu_memfd_alloc_check(void);
|
||||
void *qemu_memfd_alloc(const char *name, size_t size, unsigned int seals,
|
||||
int *fd, Error **errp);
|
||||
void qemu_memfd_free(void *ptr, size_t size, int fd);
|
||||
bool qemu_memfd_check(unsigned int flags);
|
||||
|
||||
#endif /* QEMU_MEMFD_H */
|
||||
@@ -0,0 +1,66 @@
|
||||
#ifndef QEMU_MMAP_ALLOC_H
|
||||
#define QEMU_MMAP_ALLOC_H
|
||||
|
||||
typedef enum {
|
||||
QEMU_FS_TYPE_UNKNOWN = 0,
|
||||
QEMU_FS_TYPE_TMPFS,
|
||||
QEMU_FS_TYPE_HUGETLBFS,
|
||||
QEMU_FS_TYPE_NUM,
|
||||
} QemuFsType;
|
||||
|
||||
size_t qemu_fd_getpagesize(int fd);
|
||||
QemuFsType qemu_fd_getfs(int fd);
|
||||
|
||||
/**
|
||||
* qemu_ram_mmap: mmap anonymous memory, the specified file or device.
|
||||
*
|
||||
* mmap() abstraction to map guest RAM, simplifying flag handling, taking
|
||||
* care of alignment requirements and installing guard pages.
|
||||
*
|
||||
* Parameters:
|
||||
* @fd: the file or the device to mmap
|
||||
* @size: the number of bytes to be mmaped
|
||||
* @align: if not zero, specify the alignment of the starting mapping address;
|
||||
* otherwise, the alignment in use will be determined by QEMU.
|
||||
* @qemu_map_flags: QEMU_MAP_* flags
|
||||
* @map_offset: map starts at offset of map_offset from the start of fd
|
||||
*
|
||||
* Internally, MAP_PRIVATE, MAP_ANONYMOUS and MAP_SHARED_VALIDATE are set
|
||||
* implicitly based on other parameters.
|
||||
*
|
||||
* Return:
|
||||
* On success, return a pointer to the mapped area.
|
||||
* On failure, return MAP_FAILED.
|
||||
*/
|
||||
void *qemu_ram_mmap(int fd,
|
||||
size_t size,
|
||||
size_t align,
|
||||
uint32_t qemu_map_flags,
|
||||
off_t map_offset);
|
||||
|
||||
void qemu_ram_munmap(int fd, void *ptr, size_t size);
|
||||
|
||||
/*
|
||||
* Abstraction of PROT_ and MAP_ flags as passed to mmap(), for example,
|
||||
* consumed by qemu_ram_mmap().
|
||||
*/
|
||||
|
||||
/* Map PROT_READ instead of PROT_READ | PROT_WRITE. */
|
||||
#define QEMU_MAP_READONLY (1 << 0)
|
||||
|
||||
/* Use MAP_SHARED instead of MAP_PRIVATE. */
|
||||
#define QEMU_MAP_SHARED (1 << 1)
|
||||
|
||||
/*
|
||||
* Use MAP_SYNC | MAP_SHARED_VALIDATE if supported. Ignored without
|
||||
* QEMU_MAP_SHARED. If mapping fails, warn and fallback to !QEMU_MAP_SYNC.
|
||||
*/
|
||||
#define QEMU_MAP_SYNC (1 << 2)
|
||||
|
||||
/*
|
||||
* Use MAP_NORESERVE to skip reservation of swap space (or huge pages if
|
||||
* applicable). Bail out if not supported/effective.
|
||||
*/
|
||||
#define QEMU_MAP_NORESERVE (1 << 3)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* QEMU Module Infrastructure
|
||||
*
|
||||
* Copyright IBM, Corp. 2009
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <[email protected]>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QEMU_MODULE_H
|
||||
#define QEMU_MODULE_H
|
||||
|
||||
|
||||
#define DSO_STAMP_FUN glue(qemu_stamp, CONFIG_STAMP)
|
||||
#define DSO_STAMP_FUN_STR stringify(DSO_STAMP_FUN)
|
||||
|
||||
#ifdef BUILD_DSO
|
||||
void DSO_STAMP_FUN(void);
|
||||
/* This is a dummy symbol to identify a loaded DSO as a QEMU module, so we can
|
||||
* distinguish "version mismatch" from "not a QEMU module", when the stamp
|
||||
* check fails during module loading */
|
||||
void qemu_module_dummy(void);
|
||||
|
||||
#define module_init(function, type) \
|
||||
static void __attribute__((constructor)) do_qemu_init_ ## function(void) \
|
||||
{ \
|
||||
register_dso_module_init(function, type); \
|
||||
}
|
||||
#else
|
||||
/* This should not be used directly. Use block_init etc. instead. */
|
||||
#define module_init(function, type) \
|
||||
static void __attribute__((constructor)) do_qemu_init_ ## function(void) \
|
||||
{ \
|
||||
register_module_init(function, type); \
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
MODULE_INIT_MIGRATION,
|
||||
MODULE_INIT_BLOCK,
|
||||
MODULE_INIT_OPTS,
|
||||
MODULE_INIT_TARGET_INFO,
|
||||
MODULE_INIT_QOM,
|
||||
MODULE_INIT_TRACE,
|
||||
MODULE_INIT_XEN_BACKEND,
|
||||
MODULE_INIT_LIBQOS,
|
||||
MODULE_INIT_FUZZ_TARGET,
|
||||
MODULE_INIT_MAX
|
||||
} module_init_type;
|
||||
|
||||
#define block_init(function) module_init(function, MODULE_INIT_BLOCK)
|
||||
#define opts_init(function) module_init(function, MODULE_INIT_OPTS)
|
||||
#define type_init(function) module_init(function, MODULE_INIT_QOM)
|
||||
#define trace_init(function) module_init(function, MODULE_INIT_TRACE)
|
||||
#define xen_backend_init(function) module_init(function, \
|
||||
MODULE_INIT_XEN_BACKEND)
|
||||
#define libqos_init(function) module_init(function, MODULE_INIT_LIBQOS)
|
||||
#define fuzz_target_init(function) module_init(function, \
|
||||
MODULE_INIT_FUZZ_TARGET)
|
||||
#define migration_init(function) module_init(function, MODULE_INIT_MIGRATION)
|
||||
#define block_module_load(lib, errp) module_load("block-", lib, errp)
|
||||
#define ui_module_load(lib, errp) module_load("ui-", lib, errp)
|
||||
|
||||
void register_module_init(void (*fn)(void), module_init_type type);
|
||||
void register_dso_module_init(void (*fn)(void), module_init_type type);
|
||||
|
||||
void module_call_init(module_init_type type);
|
||||
|
||||
/*
|
||||
* module_load: attempt to load a module from a set of directories
|
||||
*
|
||||
* directories searched are:
|
||||
* - getenv("QEMU_MODULE_DIR")
|
||||
* - get_relocated_path(CONFIG_QEMU_MODDIR);
|
||||
* - /var/run/qemu/${version_dir}
|
||||
*
|
||||
* prefix: a subsystem prefix, or the empty string ("ui-", ..., "")
|
||||
* name: name of the module
|
||||
* errp: error to set in case the module is found, but load failed.
|
||||
*
|
||||
* Return value: -1 on error (errp set if not NULL).
|
||||
* 0 if module or one of its dependencies are not installed,
|
||||
* 1 if the module is found and loaded,
|
||||
* 2 if the module is already loaded, or module is built-in.
|
||||
*/
|
||||
int module_load(const char *prefix, const char *name, Error **errp);
|
||||
|
||||
/*
|
||||
* module_load_qom: attempt to load a module to provide a QOM type
|
||||
*
|
||||
* type: the type to be provided
|
||||
* errp: error to set.
|
||||
*
|
||||
* Return value: as per module_load.
|
||||
*/
|
||||
int module_load_qom(const char *type, Error **errp);
|
||||
void module_load_qom_all(void);
|
||||
void module_allow_arch(const char *arch);
|
||||
|
||||
/**
|
||||
* DOC: module info annotation macros
|
||||
*
|
||||
* ``scripts/modinfo-collect.py`` will collect module info,
|
||||
* using the preprocessor and -DQEMU_MODINFO.
|
||||
*
|
||||
* ``scripts/modinfo-generate.py`` will create a module meta-data database
|
||||
* from the collected information so qemu knows about module
|
||||
* dependencies and QOM objects implemented by modules.
|
||||
*
|
||||
* See ``*.modinfo`` and ``modinfo.c`` in the build directory to check the
|
||||
* script results.
|
||||
*/
|
||||
#ifdef QEMU_MODINFO
|
||||
# define modinfo(kind, value) \
|
||||
MODINFO_START kind value MODINFO_END
|
||||
#else
|
||||
# define modinfo(kind, value)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* module_obj
|
||||
*
|
||||
* @name: QOM type.
|
||||
*
|
||||
* This module implements QOM type @name.
|
||||
*/
|
||||
#define module_obj(name) modinfo(obj, name)
|
||||
|
||||
/**
|
||||
* module_dep
|
||||
*
|
||||
* @name: module name
|
||||
*
|
||||
* This module depends on module @name.
|
||||
*/
|
||||
#define module_dep(name) modinfo(dep, name)
|
||||
|
||||
/**
|
||||
* module_arch
|
||||
*
|
||||
* @name: target architecture
|
||||
*
|
||||
* This module is for target architecture @arch.
|
||||
*
|
||||
* Note that target-dependent modules are tagged automatically, so
|
||||
* this is only needed in case target-independent modules should be
|
||||
* restricted. Use case example: the ccw bus is implemented by s390x
|
||||
* only.
|
||||
*/
|
||||
#define module_arch(name) modinfo(arch, name)
|
||||
|
||||
/**
|
||||
* module_opts
|
||||
*
|
||||
* @name: QemuOpts name
|
||||
*
|
||||
* This module registers QemuOpts @name.
|
||||
*/
|
||||
#define module_opts(name) modinfo(opts, name)
|
||||
|
||||
/**
|
||||
* module_kconfig
|
||||
*
|
||||
* @name: Kconfig requirement necessary to load the module
|
||||
*
|
||||
* This module requires a core module that should be implemented and
|
||||
* enabled in Kconfig.
|
||||
*/
|
||||
#define module_kconfig(name) modinfo(kconfig, name)
|
||||
|
||||
/*
|
||||
* module info database
|
||||
*
|
||||
* scripts/modinfo-generate.c will build this using the data collected
|
||||
* by scripts/modinfo-collect.py
|
||||
*/
|
||||
typedef struct QemuModinfo QemuModinfo;
|
||||
struct QemuModinfo {
|
||||
const char *name;
|
||||
const char *arch;
|
||||
const char **objs;
|
||||
const char **deps;
|
||||
const char **opts;
|
||||
};
|
||||
extern const QemuModinfo qemu_modinfo[];
|
||||
void module_init_info(const QemuModinfo *info);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* QEMU mprotect functions
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
#ifndef QEMU_MPROTECT_H
|
||||
#define QEMU_MPROTECT_H
|
||||
|
||||
int qemu_mprotect_rw(void *addr, size_t size);
|
||||
int qemu_mprotect_rwx(void *addr, size_t size);
|
||||
int qemu_mprotect_none(void *addr, size_t size);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Notifier lists
|
||||
*
|
||||
* Copyright IBM, Corp. 2010
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <[email protected]>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QEMU_NOTIFY_H
|
||||
#define QEMU_NOTIFY_H
|
||||
|
||||
#include "qemu/queue.h"
|
||||
|
||||
typedef struct Notifier Notifier;
|
||||
|
||||
struct Notifier
|
||||
{
|
||||
void (*notify)(Notifier *notifier, void *data);
|
||||
QLIST_ENTRY(Notifier) node;
|
||||
};
|
||||
|
||||
typedef struct NotifierList
|
||||
{
|
||||
QLIST_HEAD(, Notifier) notifiers;
|
||||
} NotifierList;
|
||||
|
||||
#define NOTIFIER_LIST_INITIALIZER(head) \
|
||||
{ QLIST_HEAD_INITIALIZER((head).notifiers) }
|
||||
|
||||
void notifier_list_init(NotifierList *list);
|
||||
|
||||
void notifier_list_add(NotifierList *list, Notifier *notifier);
|
||||
|
||||
void notifier_remove(Notifier *notifier);
|
||||
|
||||
void notifier_list_notify(NotifierList *list, void *data);
|
||||
|
||||
bool notifier_list_empty(NotifierList *list);
|
||||
|
||||
/* Same as Notifier but allows .notify() to return errors */
|
||||
typedef struct NotifierWithReturn NotifierWithReturn;
|
||||
|
||||
/* Return int to allow for different failure modes and recovery actions */
|
||||
typedef int (*NotifierWithReturnFunc)(NotifierWithReturn *notifier, void *data,
|
||||
Error **errp);
|
||||
|
||||
struct NotifierWithReturn {
|
||||
/**
|
||||
* Return 0 on success (next notifier will be invoked), otherwise
|
||||
* notifier_with_return_list_notify() will stop and return the value.
|
||||
*/
|
||||
NotifierWithReturnFunc notify;
|
||||
QLIST_ENTRY(NotifierWithReturn) node;
|
||||
};
|
||||
|
||||
typedef struct NotifierWithReturnList {
|
||||
QLIST_HEAD(, NotifierWithReturn) notifiers;
|
||||
} NotifierWithReturnList;
|
||||
|
||||
#define NOTIFIER_WITH_RETURN_LIST_INITIALIZER(head) \
|
||||
{ QLIST_HEAD_INITIALIZER((head).notifiers) }
|
||||
|
||||
void notifier_with_return_list_init(NotifierWithReturnList *list);
|
||||
|
||||
void notifier_with_return_list_add(NotifierWithReturnList *list,
|
||||
NotifierWithReturn *notifier);
|
||||
|
||||
void notifier_with_return_remove(NotifierWithReturn *notifier);
|
||||
|
||||
int notifier_with_return_list_notify(NotifierWithReturnList *list,
|
||||
void *data, Error **errp);
|
||||
|
||||
bool notifier_with_return_list_empty(NotifierWithReturnList *list);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,6 @@
|
||||
#ifndef NVDIMM_UTILS_H
|
||||
#define NVDIMM_UTILS_H
|
||||
|
||||
|
||||
GSList *nvdimm_get_device_list(void);
|
||||
#endif
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Commandline option parsing functions
|
||||
*
|
||||
* Copyright (c) 2003-2008 Fabrice Bellard
|
||||
* Copyright (c) 2009 Kevin Wolf <[email protected]>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_OPTION_H
|
||||
#define QEMU_OPTION_H
|
||||
|
||||
#include "qemu/queue.h"
|
||||
|
||||
/**
|
||||
* get_opt_value
|
||||
* @p: a pointer to the option name, delimited by commas
|
||||
* @value: a non-NULL pointer that will received the delimited options
|
||||
*
|
||||
* The @value char pointer will be allocated and filled with
|
||||
* the delimited options.
|
||||
*
|
||||
* Returns the position of the comma delimiter/zero byte after the
|
||||
* option name in @p.
|
||||
* The memory pointer in @value must be released with a call to g_free()
|
||||
* when no longer required.
|
||||
*/
|
||||
const char *get_opt_value(const char *p, char **value);
|
||||
|
||||
bool parse_option_size(const char *name, const char *value,
|
||||
uint64_t *ret, Error **errp);
|
||||
bool has_help_option(const char *param);
|
||||
|
||||
enum QemuOptType {
|
||||
QEMU_OPT_STRING = 0, /* no parsing (use string as-is) */
|
||||
QEMU_OPT_BOOL, /* on/off */
|
||||
QEMU_OPT_NUMBER, /* simple number */
|
||||
QEMU_OPT_SIZE, /* size, accepts (K)ilo, (M)ega, (G)iga, (T)era postfix */
|
||||
};
|
||||
|
||||
typedef struct QemuOpt QemuOpt;
|
||||
|
||||
typedef struct QemuOptDesc {
|
||||
const char *name;
|
||||
enum QemuOptType type;
|
||||
const char *help;
|
||||
const char *def_value_str;
|
||||
} QemuOptDesc;
|
||||
|
||||
struct QemuOptsList {
|
||||
const char *name;
|
||||
const char *implied_opt_name;
|
||||
bool merge_lists; /* Merge multiple uses of option into a single list? */
|
||||
QTAILQ_HEAD(, QemuOpts) head;
|
||||
QemuOptDesc desc[];
|
||||
};
|
||||
|
||||
const char *qemu_opt_get(QemuOpts *opts, const char *name);
|
||||
char *qemu_opt_get_del(QemuOpts *opts, const char *name);
|
||||
bool qemu_opt_has_any(QemuOpts *opts, const char * const *names);
|
||||
/**
|
||||
* qemu_opt_has_help_opt:
|
||||
* @opts: options to search for a help request
|
||||
*
|
||||
* Check whether the options specified by @opts include one of the
|
||||
* standard strings which indicate that the user is asking for a
|
||||
* list of the valid values for a command line option (as defined
|
||||
* by is_help_option()).
|
||||
*
|
||||
* Returns: true if @opts includes 'help' or equivalent.
|
||||
*/
|
||||
bool qemu_opt_has_help_opt(QemuOpts *opts);
|
||||
QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name);
|
||||
bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval);
|
||||
uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval);
|
||||
uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval);
|
||||
bool qemu_opt_get_bool_del(QemuOpts *opts, const char *name, bool defval);
|
||||
uint64_t qemu_opt_get_number_del(QemuOpts *opts, const char *name,
|
||||
uint64_t defval);
|
||||
uint64_t qemu_opt_get_size_del(QemuOpts *opts, const char *name,
|
||||
uint64_t defval);
|
||||
int qemu_opt_unset(QemuOpts *opts, const char *name);
|
||||
bool qemu_opt_set(QemuOpts *opts, const char *name, const char *value,
|
||||
Error **errp);
|
||||
bool qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val,
|
||||
Error **errp);
|
||||
bool qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val,
|
||||
Error **errp);
|
||||
typedef int (*qemu_opt_loopfunc)(void *opaque,
|
||||
const char *name, const char *value,
|
||||
Error **errp);
|
||||
int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
|
||||
Error **errp);
|
||||
|
||||
typedef struct {
|
||||
QemuOpts *opts;
|
||||
QemuOpt *opt;
|
||||
const char *name;
|
||||
} QemuOptsIter;
|
||||
|
||||
void qemu_opt_iter_init(QemuOptsIter *iter, QemuOpts *opts, const char *name);
|
||||
const char *qemu_opt_iter_next(QemuOptsIter *iter);
|
||||
|
||||
QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id);
|
||||
QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id,
|
||||
int fail_if_exists, Error **errp);
|
||||
void qemu_opts_reset(QemuOptsList *list);
|
||||
void qemu_opts_loc_restore(QemuOpts *opts);
|
||||
const char *qemu_opts_id(QemuOpts *opts);
|
||||
void qemu_opts_set_id(QemuOpts *opts, char *id);
|
||||
void qemu_opts_del(QemuOpts *opts);
|
||||
bool qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp);
|
||||
bool qemu_opts_do_parse(QemuOpts *opts, const char *params,
|
||||
const char *firstname, Error **errp);
|
||||
QemuOpts *qemu_opts_parse_noisily(QemuOptsList *list, const char *params,
|
||||
bool permit_abbrev);
|
||||
QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params,
|
||||
bool permit_abbrev, Error **errp);
|
||||
QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
|
||||
Error **errp);
|
||||
QDict *qemu_opts_to_qdict_filtered(QemuOpts *opts, QDict *qdict,
|
||||
QemuOptsList *list, bool del);
|
||||
QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict);
|
||||
bool qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp);
|
||||
|
||||
typedef int (*qemu_opts_loopfunc)(void *opaque, QemuOpts *opts, Error **errp);
|
||||
int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func,
|
||||
void *opaque, Error **errp);
|
||||
void qemu_opts_print(QemuOpts *opts, const char *sep);
|
||||
void qemu_opts_print_help(QemuOptsList *list, bool print_caption);
|
||||
void qemu_opts_free(QemuOptsList *list);
|
||||
QemuOptsList *qemu_opts_append(QemuOptsList *dst, QemuOptsList *list);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(QemuOpts, qemu_opts_del)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Commandline option parsing functions
|
||||
*
|
||||
* Copyright (c) 2003-2008 Fabrice Bellard
|
||||
* Copyright (c) 2009 Kevin Wolf <[email protected]>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_OPTION_INT_H
|
||||
#define QEMU_OPTION_INT_H
|
||||
|
||||
#include "qemu/option.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
struct QemuOpt {
|
||||
char *name;
|
||||
char *str;
|
||||
|
||||
const QemuOptDesc *desc;
|
||||
union {
|
||||
bool boolean;
|
||||
uint64_t uint;
|
||||
} value;
|
||||
|
||||
QemuOpts *opts;
|
||||
QTAILQ_ENTRY(QemuOpt) next;
|
||||
};
|
||||
|
||||
struct QemuOpts {
|
||||
char *id;
|
||||
QemuOptsList *list;
|
||||
Location loc;
|
||||
QTAILQ_HEAD(, QemuOpt) head;
|
||||
QTAILQ_ENTRY(QemuOpts) next;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,878 @@
|
||||
/*
|
||||
* OS includes and handling of OS dependencies
|
||||
*
|
||||
* This header exists to pull in some common system headers that
|
||||
* most code in QEMU will want, and to fix up some possible issues with
|
||||
* it (missing defines, Windows weirdness, and so on).
|
||||
*
|
||||
* To avoid getting into possible circular include dependencies, this
|
||||
* file should not include any other QEMU headers, with the exceptions
|
||||
* of config-host.h, config-target.h, qemu/compiler.h,
|
||||
* system/os-posix.h, system/os-win32.h, system/os-wasm.h, glib-compat.h and
|
||||
* qemu/typedefs.h, all of which are doing a similar job to this file
|
||||
* and are under similar constraints.
|
||||
*
|
||||
* This header also contains prototypes for functions defined in
|
||||
* os-*.c and util/oslib-*.c; those would probably be better split
|
||||
* out into separate header files.
|
||||
*
|
||||
* In an ideal world this header would contain only:
|
||||
* (1) things which everybody needs
|
||||
* (2) things without which code would work on most platforms but
|
||||
* fail to compile or misbehave on a minority of host OSes
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
#ifndef QEMU_OSDEP_H
|
||||
#define QEMU_OSDEP_H
|
||||
|
||||
#if !defined _FORTIFY_SOURCE && defined __OPTIMIZE__ && __OPTIMIZE__ && defined __linux__
|
||||
# define _FORTIFY_SOURCE 2
|
||||
#endif
|
||||
|
||||
#include "config-host.h"
|
||||
#ifdef COMPILING_PER_TARGET
|
||||
#include CONFIG_TARGET
|
||||
#else
|
||||
#include "exec/poison.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* HOST_WORDS_BIGENDIAN was replaced with HOST_BIG_ENDIAN. Prevent it from
|
||||
* creeping back in.
|
||||
*/
|
||||
#pragma GCC poison HOST_WORDS_BIGENDIAN
|
||||
|
||||
/*
|
||||
* TARGET_WORDS_BIGENDIAN was replaced with TARGET_BIG_ENDIAN. Prevent it from
|
||||
* creeping back in.
|
||||
*/
|
||||
#pragma GCC poison TARGET_WORDS_BIGENDIAN
|
||||
|
||||
#include "qemu/compiler.h"
|
||||
|
||||
/* Older versions of C++ don't get definitions of various macros from
|
||||
* stdlib.h unless we define these macros before first inclusion of
|
||||
* that system header.
|
||||
*/
|
||||
#ifndef __STDC_CONSTANT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#endif
|
||||
#ifndef __STDC_LIMIT_MACROS
|
||||
#define __STDC_LIMIT_MACROS
|
||||
#endif
|
||||
#ifndef __STDC_FORMAT_MACROS
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#endif
|
||||
|
||||
/* The following block of code temporarily renames the daemon() function so the
|
||||
* compiler does not see the warning associated with it in stdlib.h on OSX
|
||||
*/
|
||||
#ifdef __APPLE__
|
||||
#define daemon qemu_fake_daemon_function
|
||||
#include <stdlib.h>
|
||||
#undef daemon
|
||||
QEMU_EXTERN_C int daemon(int, int);
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
/* as defined in sdkddkver.h */
|
||||
#ifndef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0602 /* Windows 8 API (should be >= the one from glib) */
|
||||
#endif
|
||||
/* reduces the number of implicitly included headers */
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* enable C99/POSIX format strings (needs mingw32-runtime 3.15 or later) */
|
||||
#ifdef __MINGW32__
|
||||
#define __USE_MINGW_ANSI_STDIO 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We need the FreeBSD "legacy" definitions. Rust needs the FreeBSD 11 system
|
||||
* calls since it doesn't use libc at all, so we have to emulate that despite
|
||||
* FreeBSD 11 being EOL'd.
|
||||
*/
|
||||
#ifdef __FreeBSD__
|
||||
#define _WANT_FREEBSD11_STAT
|
||||
#define _WANT_FREEBSD11_STATFS
|
||||
#define _WANT_FREEBSD11_DIRENT
|
||||
#define _WANT_KERNEL_ERRNO
|
||||
#define _WANT_SEMUN
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
/* Put unistd.h before time.h as that triggers localtime_r/gmtime_r
|
||||
* function availability on recentish Mingw-w64 platforms. */
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <assert.h>
|
||||
/* setjmp must be declared before system/os-win32.h
|
||||
* because it is redefined there. */
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
|
||||
/*
|
||||
* Avoid conflict with linux/arch/powerpc/include/uapi/asm/elf.h, included
|
||||
* from <asm/sigcontext.h>, but we might as well do this unconditionally.
|
||||
*/
|
||||
#undef ELF_CLASS
|
||||
#undef ELF_DATA
|
||||
#undef ELF_ARCH
|
||||
|
||||
/*
|
||||
* Avoid conflict with Solaris FSCALE definition from <sys/param.h> header,
|
||||
* but we might as well do this unconditionally.
|
||||
*/
|
||||
#undef FSCALE
|
||||
|
||||
#ifdef CONFIG_IOVEC
|
||||
#include <sys/uio.h>
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && defined(__sparc__)
|
||||
/* The SPARC definition of QEMU_VMALLOC_ALIGN needs SHMLBA */
|
||||
#include <sys/shm.h>
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/wait.h>
|
||||
#else
|
||||
#define WIFEXITED(x) 1
|
||||
#define WEXITSTATUS(x) (x)
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <AvailabilityMacros.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is somewhat like a system header; it must be outside any extern "C"
|
||||
* block because it includes system headers itself, including glib.h,
|
||||
* which will not compile if inside an extern "C" block.
|
||||
*/
|
||||
#include "glib-compat.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "system/os-win32.h"
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_POSIX) && !defined(EMSCRIPTEN)
|
||||
#include "system/os-posix.h"
|
||||
#endif
|
||||
|
||||
#if defined(EMSCRIPTEN)
|
||||
#include "system/os-wasm.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "qemu/typedefs.h"
|
||||
|
||||
/**
|
||||
* Mark a function that executes in coroutine context
|
||||
*
|
||||
* Functions that execute in coroutine context cannot be called directly from
|
||||
* normal functions. In the future it would be nice to enable compiler or
|
||||
* static checker support for catching such errors. This annotation might make
|
||||
* it possible and in the meantime it serves as documentation.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* static void coroutine_fn foo(void) {
|
||||
* ....
|
||||
* }
|
||||
*/
|
||||
#ifdef __clang__
|
||||
#define coroutine_fn QEMU_ANNOTATE("coroutine_fn")
|
||||
#else
|
||||
#define coroutine_fn
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Mark a function that can suspend when executed in coroutine context,
|
||||
* but can handle running in non-coroutine context too.
|
||||
*/
|
||||
#ifdef __clang__
|
||||
#define coroutine_mixed_fn QEMU_ANNOTATE("coroutine_mixed_fn")
|
||||
#else
|
||||
#define coroutine_mixed_fn
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Mark a function that should not be called from a coroutine context.
|
||||
* Usually there will be an analogous, coroutine_fn function that should
|
||||
* be used instead.
|
||||
*
|
||||
* When the function is also marked as coroutine_mixed_fn, the function should
|
||||
* only be called if the caller does not know whether it is in coroutine
|
||||
* context.
|
||||
*
|
||||
* Functions that are only no_coroutine_fn, on the other hand, should not
|
||||
* be called from within coroutines at all. This for example includes
|
||||
* functions that block.
|
||||
*
|
||||
* In the future it would be nice to enable compiler or static checker
|
||||
* support for catching such errors. This annotation is the first step
|
||||
* towards this, and in the meantime it serves as documentation.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* static void no_coroutine_fn foo(void) {
|
||||
* ....
|
||||
* }
|
||||
*/
|
||||
#ifdef __clang__
|
||||
#define no_coroutine_fn QEMU_ANNOTATE("no_coroutine_fn")
|
||||
#else
|
||||
#define no_coroutine_fn
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* For mingw, as of v6.0.0, the function implementing the assert macro is
|
||||
* not marked as noreturn, so the compiler cannot delete code following an
|
||||
* assert(false) as unused. We rely on this within the code base to delete
|
||||
* code that is unreachable when features are disabled.
|
||||
* All supported versions of Glib's g_assert() satisfy this requirement.
|
||||
*/
|
||||
#ifdef __MINGW32__
|
||||
#undef assert
|
||||
#define assert(x) g_assert(x)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* qemu_build_not_reached()
|
||||
*
|
||||
* The compiler, during optimization, is expected to prove that a call
|
||||
* to this function cannot be reached and remove it. If the compiler
|
||||
* supports QEMU_ERROR, this will be reported at compile time; otherwise
|
||||
* this will be reported at link time due to the missing symbol.
|
||||
*/
|
||||
G_NORETURN
|
||||
void QEMU_ERROR("code path is reachable")
|
||||
qemu_build_not_reached_always(void);
|
||||
#if defined(__OPTIMIZE__) && !defined(__NO_INLINE__)
|
||||
#define qemu_build_not_reached() qemu_build_not_reached_always()
|
||||
#else
|
||||
#define qemu_build_not_reached() g_assert_not_reached()
|
||||
#endif
|
||||
|
||||
/**
|
||||
* qemu_build_assert()
|
||||
*
|
||||
* The compiler, during optimization, is expected to prove that the
|
||||
* assertion is true.
|
||||
*/
|
||||
#define qemu_build_assert(test) while (!(test)) qemu_build_not_reached()
|
||||
|
||||
/*
|
||||
* According to waitpid man page:
|
||||
* WCOREDUMP
|
||||
* This macro is not specified in POSIX.1-2001 and is not
|
||||
* available on some UNIX implementations (e.g., AIX, SunOS).
|
||||
* Therefore, enclose its use inside #ifdef WCOREDUMP ... #endif.
|
||||
*/
|
||||
#ifndef WCOREDUMP
|
||||
#define WCOREDUMP(status) 0
|
||||
#endif
|
||||
/*
|
||||
* We have a lot of unaudited code that may fail in strange ways, or
|
||||
* even be a security risk during migration, if you disable assertions
|
||||
* at compile-time. You may comment out these safety checks if you
|
||||
* absolutely want to disable assertion overhead, but it is not
|
||||
* supported upstream so the risk is all yours. Meanwhile, please
|
||||
* submit patches to remove any side-effects inside an assertion, or
|
||||
* fixing error handling that should use Error instead of assert.
|
||||
*/
|
||||
#ifdef NDEBUG
|
||||
#error building with NDEBUG is not supported
|
||||
#endif
|
||||
#ifdef G_DISABLE_ASSERT
|
||||
#error building with G_DISABLE_ASSERT is not supported
|
||||
#endif
|
||||
|
||||
#ifndef OFF_MAX
|
||||
#define OFF_MAX (sizeof (off_t) == 8 ? INT64_MAX : INT32_MAX)
|
||||
#endif
|
||||
|
||||
#ifndef O_LARGEFILE
|
||||
#define O_LARGEFILE 0
|
||||
#endif
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
#ifndef MAP_ANONYMOUS
|
||||
#define MAP_ANONYMOUS MAP_ANON
|
||||
#endif
|
||||
#ifndef MAP_NORESERVE
|
||||
#define MAP_NORESERVE 0
|
||||
#endif
|
||||
#ifndef ENOMEDIUM
|
||||
#define ENOMEDIUM ENODEV
|
||||
#endif
|
||||
#if !defined(ENOTSUP)
|
||||
#define ENOTSUP 4096
|
||||
#endif
|
||||
#if !defined(ECANCELED)
|
||||
#define ECANCELED 4097
|
||||
#endif
|
||||
#if !defined(EMEDIUMTYPE)
|
||||
#define EMEDIUMTYPE 4098
|
||||
#endif
|
||||
#if !defined(ESHUTDOWN)
|
||||
#define ESHUTDOWN 4099
|
||||
#endif
|
||||
|
||||
#define RETRY_ON_EINTR(expr) \
|
||||
(__extension__ \
|
||||
({ typeof(expr) __result; \
|
||||
do { \
|
||||
__result = (expr); \
|
||||
} while (__result == -1 && errno == EINTR); \
|
||||
__result; }))
|
||||
|
||||
/* time_t may be either 32 or 64 bits depending on the host OS, and
|
||||
* can be either signed or unsigned, so we can't just hardcode a
|
||||
* specific maximum value. This is not a C preprocessor constant,
|
||||
* so you can't use TIME_MAX in an #ifdef, but for our purposes
|
||||
* this isn't a problem.
|
||||
*/
|
||||
|
||||
/* The macros TYPE_SIGNED, TYPE_WIDTH, and TYPE_MAXIMUM are from
|
||||
* Gnulib, and are under the LGPL v2.1 or (at your option) any
|
||||
* later version.
|
||||
*/
|
||||
|
||||
/* True if the real type T is signed. */
|
||||
#define TYPE_SIGNED(t) (!((t)0 < (t)-1))
|
||||
|
||||
/* The width in bits of the integer type or expression T.
|
||||
* Padding bits are not supported.
|
||||
*/
|
||||
#define TYPE_WIDTH(t) (sizeof(t) * CHAR_BIT)
|
||||
|
||||
/* The maximum and minimum values for the integer type T. */
|
||||
#define TYPE_MAXIMUM(t) \
|
||||
((t) (!TYPE_SIGNED(t) \
|
||||
? (t)-1 \
|
||||
: ((((t)1 << (TYPE_WIDTH(t) - 2)) - 1) * 2 + 1)))
|
||||
|
||||
#ifndef TIME_MAX
|
||||
#define TIME_MAX TYPE_MAXIMUM(time_t)
|
||||
#endif
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX 1024
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Use the same value as Linux for now.
|
||||
*/
|
||||
#ifndef IOV_MAX
|
||||
#define IOV_MAX 1024
|
||||
#endif
|
||||
|
||||
/* Mac OSX has a <stdint.h> bug that incorrectly defines SIZE_MAX with
|
||||
* the wrong type. Our replacement isn't usable in preprocessor
|
||||
* expressions, but it is sufficient for our needs. */
|
||||
#ifdef HAVE_BROKEN_SIZE_MAX
|
||||
#undef SIZE_MAX
|
||||
#define SIZE_MAX ((size_t)-1)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Two variations of MIN/MAX macros. The first is for runtime use, and
|
||||
* evaluates arguments only once (so it is safe even with side
|
||||
* effects), but will not work in constant contexts (such as array
|
||||
* size declarations) because of the '{}'. The second is for constant
|
||||
* expression use, where evaluating arguments twice is safe because
|
||||
* the result is going to be constant anyway, but will not work in a
|
||||
* runtime context because of a void expression where a value is
|
||||
* expected. Thus, both gcc and clang will fail to compile if you use
|
||||
* the wrong macro (even if the error may seem a bit cryptic).
|
||||
*
|
||||
* Note that neither form is usable as an #if condition; if you truly
|
||||
* need to write conditional code that depends on a minimum or maximum
|
||||
* determined by the pre-processor instead of the compiler, you'll
|
||||
* have to open-code it. Sadly, Coverity is severely confused by the
|
||||
* constant variants, so we have to dumb things down there.
|
||||
*
|
||||
* Preprocessor sorcery ahead: use different identifiers for the local
|
||||
* variables in each expansion, so we can nest macro calls without
|
||||
* shadowing variables.
|
||||
*/
|
||||
#define MIN_INTERNAL(a, b, _a, _b) \
|
||||
({ \
|
||||
typeof(1 ? (a) : (b)) _a = (a), _b = (b); \
|
||||
_a < _b ? _a : _b; \
|
||||
})
|
||||
#undef MIN
|
||||
#define MIN(a, b) \
|
||||
MIN_INTERNAL((a), (b), MAKE_IDENTIFIER(_a), MAKE_IDENTIFIER(_b))
|
||||
|
||||
#define MAX_INTERNAL(a, b, _a, _b) \
|
||||
({ \
|
||||
typeof(1 ? (a) : (b)) _a = (a), _b = (b); \
|
||||
_a > _b ? _a : _b; \
|
||||
})
|
||||
#undef MAX
|
||||
#define MAX(a, b) \
|
||||
MAX_INTERNAL((a), (b), MAKE_IDENTIFIER(_a), MAKE_IDENTIFIER(_b))
|
||||
|
||||
#ifdef __COVERITY__
|
||||
# define MIN_CONST(a, b) ((a) < (b) ? (a) : (b))
|
||||
# define MAX_CONST(a, b) ((a) > (b) ? (a) : (b))
|
||||
#else
|
||||
# define MIN_CONST(a, b) \
|
||||
__builtin_choose_expr( \
|
||||
__builtin_constant_p(a) && __builtin_constant_p(b), \
|
||||
(a) < (b) ? (a) : (b), \
|
||||
((void)0))
|
||||
# define MAX_CONST(a, b) \
|
||||
__builtin_choose_expr( \
|
||||
__builtin_constant_p(a) && __builtin_constant_p(b), \
|
||||
(a) > (b) ? (a) : (b), \
|
||||
((void)0))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Minimum function that returns zero only if both values are zero.
|
||||
* Intended for use with unsigned values only.
|
||||
*
|
||||
* Preprocessor sorcery ahead: use different identifiers for the local
|
||||
* variables in each expansion, so we can nest macro calls without
|
||||
* shadowing variables.
|
||||
*/
|
||||
#define MIN_NON_ZERO_INTERNAL(a, b, _a, _b) \
|
||||
({ \
|
||||
typeof(1 ? (a) : (b)) _a = (a), _b = (b); \
|
||||
_a == 0 ? _b : (_b == 0 || _b > _a) ? _a : _b; \
|
||||
})
|
||||
#define MIN_NON_ZERO(a, b) \
|
||||
MIN_NON_ZERO_INTERNAL((a), (b), MAKE_IDENTIFIER(_a), MAKE_IDENTIFIER(_b))
|
||||
|
||||
/*
|
||||
* Round number down to multiple. Safe when m is not a power of 2 (see
|
||||
* ROUND_DOWN for a faster version when a power of 2 is guaranteed).
|
||||
*/
|
||||
#define QEMU_ALIGN_DOWN(n, m) ((n) / (m) * (m))
|
||||
|
||||
/*
|
||||
* Round number up to multiple. Safe when m is not a power of 2 (see
|
||||
* ROUND_UP for a faster version when a power of 2 is guaranteed).
|
||||
*/
|
||||
#define QEMU_ALIGN_UP(n, m) QEMU_ALIGN_DOWN((n) + (m) - 1, (m))
|
||||
|
||||
/* Check if n is a multiple of m */
|
||||
#define QEMU_IS_ALIGNED(n, m) (((n) % (m)) == 0)
|
||||
|
||||
/* n-byte align pointer down */
|
||||
#define QEMU_ALIGN_PTR_DOWN(p, n) \
|
||||
((typeof(p))QEMU_ALIGN_DOWN((uintptr_t)(p), (n)))
|
||||
|
||||
/* n-byte align pointer up */
|
||||
#define QEMU_ALIGN_PTR_UP(p, n) \
|
||||
((typeof(p))QEMU_ALIGN_UP((uintptr_t)(p), (n)))
|
||||
|
||||
/* Check if pointer p is n-bytes aligned */
|
||||
#define QEMU_PTR_IS_ALIGNED(p, n) QEMU_IS_ALIGNED((uintptr_t)(p), (n))
|
||||
|
||||
/*
|
||||
* Round number down to multiple. Requires that d be a power of 2 (see
|
||||
* QEMU_ALIGN_UP for a safer but slower version on arbitrary
|
||||
* numbers); works even if d is a smaller type than n.
|
||||
*/
|
||||
#ifndef ROUND_DOWN
|
||||
#define ROUND_DOWN(n, d) ((n) & -(0 ? (n) : (d)))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Round number up to multiple. Requires that d be a power of 2 (see
|
||||
* QEMU_ALIGN_UP for a safer but slower version on arbitrary
|
||||
* numbers); works even if d is a smaller type than n.
|
||||
*/
|
||||
#ifndef ROUND_UP
|
||||
#define ROUND_UP(n, d) ROUND_DOWN((n) + (d) - 1, (d))
|
||||
#endif
|
||||
|
||||
#ifndef DIV_ROUND_UP
|
||||
#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* &(x)[0] is always a pointer - if it's same type as x then the argument is a
|
||||
* pointer, not an array.
|
||||
*/
|
||||
#define QEMU_IS_ARRAY(x) (!__builtin_types_compatible_p(typeof(x), \
|
||||
typeof(&(x)[0])))
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(x) ((sizeof(x) / sizeof((x)[0])) + \
|
||||
QEMU_BUILD_BUG_ON_ZERO(!QEMU_IS_ARRAY(x)))
|
||||
#endif
|
||||
|
||||
int qemu_daemon(int nochdir, int noclose);
|
||||
void *qemu_anon_ram_alloc(size_t size, uint64_t *align, bool shared,
|
||||
bool noreserve);
|
||||
void qemu_anon_ram_free(void *ptr, size_t size);
|
||||
int qemu_shm_alloc(size_t size, Error **errp);
|
||||
|
||||
#ifdef _WIN32
|
||||
#define HAVE_CHARDEV_SERIAL 1
|
||||
#define HAVE_CHARDEV_PARALLEL 1
|
||||
#else
|
||||
#if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \
|
||||
|| defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \
|
||||
|| defined(__GLIBC__) || defined(__APPLE__)
|
||||
#define HAVE_CHARDEV_SERIAL 1
|
||||
#endif
|
||||
#if defined(__linux__) || defined(__FreeBSD__) \
|
||||
|| defined(__FreeBSD_kernel__) || defined(__DragonFly__)
|
||||
#define HAVE_CHARDEV_PARALLEL 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__HAIKU__)
|
||||
#define SIGIO SIGPOLL
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MADVISE_WITHOUT_PROTOTYPE
|
||||
/*
|
||||
* See MySQL bug #7156 (http://bugs.mysql.com/bug.php?id=7156) for discussion
|
||||
* about Solaris missing the madvise() prototype.
|
||||
*/
|
||||
int madvise(char *, size_t, int);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_LINUX)
|
||||
#ifndef BUS_MCEERR_AR
|
||||
#define BUS_MCEERR_AR 4
|
||||
#endif
|
||||
#ifndef BUS_MCEERR_AO
|
||||
#define BUS_MCEERR_AO 5
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && \
|
||||
(defined(__x86_64__) || defined(__aarch64__) \
|
||||
|| defined(__powerpc64__) || defined(__riscv))
|
||||
/* Use 2 MiB alignment so transparent hugepages can be used by KVM.
|
||||
Valgrind does not support alignments larger than 1 MiB,
|
||||
therefore we need special code which handles running on Valgrind. */
|
||||
# define QEMU_VMALLOC_ALIGN (512 * 4096)
|
||||
#elif defined(__linux__) && defined(__s390x__)
|
||||
/* Use 1 MiB (segment size) alignment so gmap can be used by KVM. */
|
||||
# define QEMU_VMALLOC_ALIGN (256 * 4096)
|
||||
#elif defined(__linux__) && defined(__sparc__)
|
||||
# define QEMU_VMALLOC_ALIGN MAX(qemu_real_host_page_size(), SHMLBA)
|
||||
#elif defined(__linux__) && defined(__loongarch__)
|
||||
/*
|
||||
* For transparent hugepage optimization, it has better be huge page
|
||||
* aligned. LoongArch host system supports two kinds of pagesize: 4K
|
||||
* and 16K, here calculate huge page size from host page size
|
||||
*/
|
||||
# define QEMU_VMALLOC_ALIGN (qemu_real_host_page_size() * \
|
||||
qemu_real_host_page_size() / sizeof(long))
|
||||
#else
|
||||
# define QEMU_VMALLOC_ALIGN qemu_real_host_page_size()
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_POSIX
|
||||
struct qemu_signalfd_siginfo {
|
||||
uint32_t ssi_signo; /* Signal number */
|
||||
int32_t ssi_errno; /* Error number (unused) */
|
||||
int32_t ssi_code; /* Signal code */
|
||||
uint32_t ssi_pid; /* PID of sender */
|
||||
uint32_t ssi_uid; /* Real UID of sender */
|
||||
int32_t ssi_fd; /* File descriptor (SIGIO) */
|
||||
uint32_t ssi_tid; /* Kernel timer ID (POSIX timers) */
|
||||
uint32_t ssi_band; /* Band event (SIGIO) */
|
||||
uint32_t ssi_overrun; /* POSIX timer overrun count */
|
||||
uint32_t ssi_trapno; /* Trap number that caused signal */
|
||||
int32_t ssi_status; /* Exit status or signal (SIGCHLD) */
|
||||
int32_t ssi_int; /* Integer sent by sigqueue(2) */
|
||||
uint64_t ssi_ptr; /* Pointer sent by sigqueue(2) */
|
||||
uint64_t ssi_utime; /* User CPU time consumed (SIGCHLD) */
|
||||
uint64_t ssi_stime; /* System CPU time consumed (SIGCHLD) */
|
||||
uint64_t ssi_addr; /* Address that generated signal
|
||||
(for hardware-generated signals) */
|
||||
uint8_t pad[48]; /* Pad size to 128 bytes (allow for
|
||||
additional fields in the future) */
|
||||
};
|
||||
|
||||
int qemu_signalfd(const sigset_t *mask);
|
||||
void sigaction_invoke(struct sigaction *action,
|
||||
struct qemu_signalfd_siginfo *info);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Don't introduce new usage of this function, prefer the following
|
||||
* qemu_open/qemu_create that take an "Error **errp"
|
||||
*/
|
||||
int qemu_open_old(const char *name, int flags, ...);
|
||||
int qemu_open(const char *name, int flags, Error **errp);
|
||||
int qemu_create(const char *name, int flags, mode_t mode, Error **errp);
|
||||
int qemu_close(int fd);
|
||||
int qemu_unlink(const char *name);
|
||||
#ifndef _WIN32
|
||||
int qemu_dup_flags(int fd, int flags);
|
||||
int qemu_dup(int fd);
|
||||
int qemu_lock_fd(int fd, int64_t start, int64_t len, bool exclusive);
|
||||
int qemu_unlock_fd(int fd, int64_t start, int64_t len);
|
||||
int qemu_lock_fd_test(int fd, int64_t start, int64_t len, bool exclusive);
|
||||
bool qemu_has_ofd_lock(void);
|
||||
int qemu_fcntl_addfl(int fd, int flag);
|
||||
#endif
|
||||
|
||||
bool qemu_has_direct_io(void);
|
||||
|
||||
#ifdef WIN64
|
||||
#define FMT_pid "%" PRId64
|
||||
#else
|
||||
#define FMT_pid "%d"
|
||||
#endif
|
||||
|
||||
bool qemu_write_pidfile(const char *pidfile, Error **errp);
|
||||
|
||||
int qemu_get_thread_id(void);
|
||||
|
||||
/**
|
||||
* qemu_kill_thread:
|
||||
* @tid: thread id.
|
||||
* @sig: host signal.
|
||||
*
|
||||
* Send @sig to one of QEMU's own threads with identifier @tid.
|
||||
*/
|
||||
int qemu_kill_thread(int tid, int sig);
|
||||
|
||||
#ifndef CONFIG_IOVEC
|
||||
struct iovec {
|
||||
void *iov_base;
|
||||
size_t iov_len;
|
||||
};
|
||||
|
||||
ssize_t readv(int fd, const struct iovec *iov, int iov_cnt);
|
||||
ssize_t writev(int fd, const struct iovec *iov, int iov_cnt);
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
static inline void qemu_timersub(const struct timeval *val1,
|
||||
const struct timeval *val2,
|
||||
struct timeval *res)
|
||||
{
|
||||
res->tv_sec = val1->tv_sec - val2->tv_sec;
|
||||
if (val1->tv_usec < val2->tv_usec) {
|
||||
res->tv_sec--;
|
||||
res->tv_usec = val1->tv_usec - val2->tv_usec + 1000 * 1000;
|
||||
} else {
|
||||
res->tv_usec = val1->tv_usec - val2->tv_usec;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define qemu_timersub timersub
|
||||
#endif
|
||||
|
||||
ssize_t qemu_write_full(int fd, const void *buf, size_t count)
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
void qemu_set_cloexec(int fd);
|
||||
bool qemu_set_blocking(int fd, bool block, Error **errp);
|
||||
|
||||
/*
|
||||
* Clear FD_CLOEXEC for a descriptor.
|
||||
*
|
||||
* The caller must guarantee that no other fork+exec's occur before the
|
||||
* exec that is intended to inherit this descriptor, eg by suspending CPUs
|
||||
* and blocking monitor commands.
|
||||
*/
|
||||
void qemu_clear_cloexec(int fd);
|
||||
|
||||
/* Return a dynamically allocated directory path that is appropriate for storing
|
||||
* local state.
|
||||
*
|
||||
* The caller is responsible for releasing the value returned with g_free()
|
||||
* after use.
|
||||
*/
|
||||
char *qemu_get_local_state_dir(void);
|
||||
|
||||
/**
|
||||
* qemu_getauxval:
|
||||
* @type: the auxiliary vector key to lookup
|
||||
*
|
||||
* Search the auxiliary vector for @type, returning the value
|
||||
* or 0 if @type is not present.
|
||||
*/
|
||||
unsigned long qemu_getauxval(unsigned long type);
|
||||
|
||||
void qemu_set_tty_echo(int fd, bool echo);
|
||||
|
||||
typedef struct ThreadContext ThreadContext;
|
||||
|
||||
/**
|
||||
* qemu_prealloc_mem:
|
||||
* @fd: the fd mapped into the area, -1 for anonymous memory
|
||||
* @area: start address of the are to preallocate
|
||||
* @sz: the size of the area to preallocate
|
||||
* @max_threads: maximum number of threads to use
|
||||
* @tc: prealloc context threads pointer, NULL if not in use
|
||||
* @async: request asynchronous preallocation, requires @tc
|
||||
* @errp: returns an error if this function fails
|
||||
*
|
||||
* Preallocate memory (populate/prefault page tables writable) for the virtual
|
||||
* memory area starting at @area with the size of @sz. After a successful call,
|
||||
* each page in the area was faulted in writable at least once, for example,
|
||||
* after allocating file blocks for mapped files.
|
||||
*
|
||||
* When setting @async, allocation might be performed asynchronously.
|
||||
* qemu_finish_async_prealloc_mem() must be called to finish any asynchronous
|
||||
* preallocation.
|
||||
*
|
||||
* Return: true on success, else false setting @errp with error.
|
||||
*/
|
||||
bool qemu_prealloc_mem(int fd, char *area, size_t sz, int max_threads,
|
||||
ThreadContext *tc, bool async, Error **errp);
|
||||
|
||||
/**
|
||||
* qemu_finish_async_prealloc_mem:
|
||||
* @errp: returns an error if this function fails
|
||||
*
|
||||
* Finish all outstanding asynchronous memory preallocation.
|
||||
*
|
||||
* Return: true on success, else false setting @errp with error.
|
||||
*/
|
||||
bool qemu_finish_async_prealloc_mem(Error **errp);
|
||||
|
||||
/**
|
||||
* qemu_get_pid_name:
|
||||
* @pid: pid of a process
|
||||
*
|
||||
* For given @pid fetch its name. Caller is responsible for
|
||||
* freeing the string when no longer needed.
|
||||
* Returns allocated string on success, NULL on failure.
|
||||
*/
|
||||
char *qemu_get_pid_name(pid_t pid);
|
||||
|
||||
/* Using intptr_t ensures that qemu_*_page_mask is sign-extended even
|
||||
* when intptr_t is 32-bit and we are aligning a long long.
|
||||
*/
|
||||
static inline uintptr_t qemu_real_host_page_size(void)
|
||||
{
|
||||
return getpagesize();
|
||||
}
|
||||
|
||||
static inline intptr_t qemu_real_host_page_mask(void)
|
||||
{
|
||||
return -(intptr_t)qemu_real_host_page_size();
|
||||
}
|
||||
|
||||
/*
|
||||
* After using getopt or getopt_long, if you need to parse another set
|
||||
* of options, then you must reset optind. Unfortunately the way to
|
||||
* do this varies between implementations of getopt.
|
||||
*/
|
||||
static inline void qemu_reset_optind(void)
|
||||
{
|
||||
#ifdef HAVE_OPTRESET
|
||||
optind = 1;
|
||||
optreset = 1;
|
||||
#else
|
||||
optind = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int qemu_fdatasync(int fd);
|
||||
|
||||
/**
|
||||
* qemu_close_all_open_fd:
|
||||
*
|
||||
* Close all open file descriptors except the ones supplied in the @skip array
|
||||
*
|
||||
* @skip: ordered array of distinct file descriptors that should not be closed
|
||||
* if any, or NULL.
|
||||
* @nskip: number of entries in the @skip array or 0 if @skip is NULL.
|
||||
*/
|
||||
void qemu_close_all_open_fd(const int *skip, unsigned int nskip);
|
||||
|
||||
/**
|
||||
* Sync changes made to the memory mapped file back to the backing
|
||||
* storage. For POSIX compliant systems this will fallback
|
||||
* to regular msync call. Otherwise it will trigger whole file sync
|
||||
* (including the metadata case there is no support to skip that otherwise)
|
||||
*
|
||||
* @addr - start of the memory area to be synced
|
||||
* @length - length of the are to be synced
|
||||
* @fd - file descriptor for the file to be synced
|
||||
* (mandatory only for POSIX non-compliant systems)
|
||||
*/
|
||||
int qemu_msync(void *addr, size_t length, int fd);
|
||||
|
||||
/**
|
||||
* qemu_get_host_physmem:
|
||||
*
|
||||
* Operating system agnostic way of querying host memory.
|
||||
*
|
||||
* Returns amount of physical memory on the system. This is purely
|
||||
* advisery and may return 0 if we can't work it out. At the other
|
||||
* end we saturate to SIZE_MAX if you are lucky enough to have that
|
||||
* much memory.
|
||||
*/
|
||||
size_t qemu_get_host_physmem(void);
|
||||
|
||||
/*
|
||||
* Toggle write/execute on the pages marked MAP_JIT
|
||||
* for the current thread.
|
||||
*/
|
||||
#ifdef __APPLE__
|
||||
static inline void qemu_thread_jit_execute(void)
|
||||
{
|
||||
pthread_jit_write_protect_np(true);
|
||||
}
|
||||
|
||||
static inline void qemu_thread_jit_write(void)
|
||||
{
|
||||
pthread_jit_write_protect_np(false);
|
||||
}
|
||||
#else
|
||||
static inline void qemu_thread_jit_write(void) {}
|
||||
static inline void qemu_thread_jit_execute(void) {}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Platforms which do not support system() return ENOSYS
|
||||
*/
|
||||
#ifndef HAVE_SYSTEM_FUNCTION
|
||||
#define system platform_does_not_support_system
|
||||
static inline int platform_does_not_support_system(const char *command)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
#endif /* !HAVE_SYSTEM_FUNCTION */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef QEMU_PATH_H
|
||||
#define QEMU_PATH_H
|
||||
|
||||
void init_paths(const char *prefix);
|
||||
const char *path(const char *pathname);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#ifndef QEMU_PCAP_H
|
||||
#define QEMU_PCAP_H
|
||||
|
||||
#define PCAP_MAGIC 0xa1b2c3d4
|
||||
#define PCAP_MAJOR 2
|
||||
#define PCAP_MINOR 4
|
||||
|
||||
/* https://wiki.wireshark.org/Development/LibpcapFileFormat */
|
||||
|
||||
struct pcap_hdr {
|
||||
uint32_t magic_number; /* magic number */
|
||||
uint16_t version_major; /* major version number */
|
||||
uint16_t version_minor; /* minor version number */
|
||||
int32_t thiszone; /* GMT to local correction */
|
||||
uint32_t sigfigs; /* accuracy of timestamps */
|
||||
uint32_t snaplen; /* max length of captured packets, in octets */
|
||||
uint32_t network; /* data link type */
|
||||
};
|
||||
|
||||
struct pcaprec_hdr {
|
||||
uint32_t ts_sec; /* timestamp seconds */
|
||||
uint32_t ts_usec; /* timestamp microseconds */
|
||||
uint32_t incl_len; /* number of octets of packet saved in file */
|
||||
uint32_t orig_len; /* actual length of packet */
|
||||
};
|
||||
|
||||
#endif /* QEMU_PCAP_H */
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2017, Emilio G. Cota <[email protected]>
|
||||
*
|
||||
* License: GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
#ifndef QEMU_PLUGIN_EVENT_H
|
||||
#define QEMU_PLUGIN_EVENT_H
|
||||
|
||||
/*
|
||||
* Events that plugins can subscribe to.
|
||||
*/
|
||||
enum qemu_plugin_event {
|
||||
QEMU_PLUGIN_EV_VCPU_INIT,
|
||||
QEMU_PLUGIN_EV_VCPU_EXIT,
|
||||
QEMU_PLUGIN_EV_VCPU_TB_TRANS,
|
||||
QEMU_PLUGIN_EV_VCPU_IDLE,
|
||||
QEMU_PLUGIN_EV_VCPU_RESUME,
|
||||
QEMU_PLUGIN_EV_VCPU_SYSCALL,
|
||||
QEMU_PLUGIN_EV_VCPU_SYSCALL_RET,
|
||||
QEMU_PLUGIN_EV_FLUSH,
|
||||
QEMU_PLUGIN_EV_ATEXIT,
|
||||
QEMU_PLUGIN_EV_VCPU_INTERRUPT,
|
||||
QEMU_PLUGIN_EV_VCPU_EXCEPTION,
|
||||
QEMU_PLUGIN_EV_VCPU_HOSTCALL,
|
||||
QEMU_PLUGIN_EV_VCPU_SYSCALL_FILTER,
|
||||
QEMU_PLUGIN_EV_MAX, /* total number of plugin events we support */
|
||||
};
|
||||
|
||||
#endif /* QEMU_PLUGIN_EVENT_H */
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Plugin Memory API
|
||||
*
|
||||
* Copyright (c) 2019 Linaro Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef PLUGIN_MEMORY_H
|
||||
#define PLUGIN_MEMORY_H
|
||||
|
||||
#include "exec/hwaddr.h"
|
||||
|
||||
struct qemu_plugin_hwaddr {
|
||||
bool is_io;
|
||||
bool is_store;
|
||||
hwaddr phys_addr;
|
||||
MemoryRegion *mr;
|
||||
};
|
||||
|
||||
/**
|
||||
* tlb_plugin_lookup: query last TLB lookup
|
||||
* @cpu: cpu environment
|
||||
*
|
||||
* This function can be used directly after a memory operation to
|
||||
* query information about the access. It is used by the plugin
|
||||
* infrastructure to expose more information about the address.
|
||||
*
|
||||
* It would only fail if not called from an instrumented memory access
|
||||
* which would be an abuse of the API.
|
||||
*/
|
||||
bool tlb_plugin_lookup(CPUState *cpu, vaddr addr, int mmu_idx,
|
||||
bool is_store, struct qemu_plugin_hwaddr *data);
|
||||
|
||||
#endif /* PLUGIN_MEMORY_H */
|
||||
@@ -0,0 +1,327 @@
|
||||
/*
|
||||
* Copyright (C) 2017, Emilio G. Cota <[email protected]>
|
||||
*
|
||||
* License: GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
#ifndef QEMU_PLUGIN_H
|
||||
#define QEMU_PLUGIN_H
|
||||
|
||||
#include "qemu/config-file.h"
|
||||
#include "plugins/qemu-plugin.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/queue.h"
|
||||
#include "qemu/option.h"
|
||||
#include "qemu/plugin-event.h"
|
||||
#include "qemu/bitmap.h"
|
||||
#include "exec/memopidx.h"
|
||||
#include "hw/core/cpu.h"
|
||||
|
||||
/*
|
||||
* Option parsing/processing.
|
||||
* Note that we can load an arbitrary number of plugins.
|
||||
*/
|
||||
struct qemu_plugin_desc;
|
||||
typedef QTAILQ_HEAD(, qemu_plugin_desc) QemuPluginList;
|
||||
|
||||
/*
|
||||
* Construct a qemu_plugin_meminfo_t.
|
||||
*/
|
||||
static inline qemu_plugin_meminfo_t
|
||||
make_plugin_meminfo(MemOpIdx oi, enum qemu_plugin_mem_rw rw)
|
||||
{
|
||||
return oi | (rw << 16);
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract the memory operation direction from a qemu_plugin_meminfo_t.
|
||||
* Other portions may be extracted via get_memop and get_mmuidx.
|
||||
*/
|
||||
static inline enum qemu_plugin_mem_rw
|
||||
get_plugin_meminfo_rw(qemu_plugin_meminfo_t i)
|
||||
{
|
||||
return i >> 16;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PLUGIN
|
||||
extern QemuOptsList qemu_plugin_opts;
|
||||
|
||||
static inline void qemu_plugin_add_opts(void)
|
||||
{
|
||||
qemu_add_opts(&qemu_plugin_opts);
|
||||
}
|
||||
|
||||
void qemu_plugin_opt_parse(const char *optstr, QemuPluginList *head);
|
||||
int qemu_plugin_load_list(QemuPluginList *head, Error **errp);
|
||||
|
||||
union qemu_plugin_cb_sig {
|
||||
qemu_plugin_udata_cb_t udata;
|
||||
qemu_plugin_vcpu_udata_cb_t vcpu_udata;
|
||||
qemu_plugin_vcpu_discon_cb_t vcpu_discon;
|
||||
qemu_plugin_vcpu_tb_trans_cb_t vcpu_tb_trans;
|
||||
qemu_plugin_vcpu_mem_cb_t vcpu_mem;
|
||||
qemu_plugin_vcpu_syscall_cb_t vcpu_syscall;
|
||||
qemu_plugin_vcpu_syscall_ret_cb_t vcpu_syscall_ret;
|
||||
qemu_plugin_vcpu_syscall_filter_cb_t vcpu_syscall_filter;
|
||||
void *generic;
|
||||
};
|
||||
|
||||
enum plugin_dyn_cb_type {
|
||||
PLUGIN_CB_REGULAR,
|
||||
PLUGIN_CB_COND,
|
||||
PLUGIN_CB_MEM_REGULAR,
|
||||
PLUGIN_CB_INLINE_ADD_U64,
|
||||
PLUGIN_CB_INLINE_STORE_U64,
|
||||
};
|
||||
|
||||
struct qemu_plugin_regular_cb {
|
||||
union qemu_plugin_cb_sig f;
|
||||
TCGHelperInfo *info;
|
||||
void *userp;
|
||||
enum qemu_plugin_mem_rw rw;
|
||||
};
|
||||
|
||||
struct qemu_plugin_inline_cb {
|
||||
qemu_plugin_u64 entry;
|
||||
uint64_t imm;
|
||||
enum qemu_plugin_mem_rw rw;
|
||||
};
|
||||
|
||||
struct qemu_plugin_conditional_cb {
|
||||
union qemu_plugin_cb_sig f;
|
||||
TCGHelperInfo *info;
|
||||
void *userp;
|
||||
qemu_plugin_u64 entry;
|
||||
enum qemu_plugin_cond cond;
|
||||
uint64_t imm;
|
||||
};
|
||||
|
||||
/*
|
||||
* A dynamic callback has an insertion point that is determined at run-time.
|
||||
* Usually the insertion point is somewhere in the code cache; think for
|
||||
* instance of a callback to be called upon the execution of a particular TB.
|
||||
*/
|
||||
struct qemu_plugin_dyn_cb {
|
||||
enum plugin_dyn_cb_type type;
|
||||
union {
|
||||
struct qemu_plugin_regular_cb regular;
|
||||
struct qemu_plugin_conditional_cb cond;
|
||||
struct qemu_plugin_inline_cb inline_insn;
|
||||
};
|
||||
};
|
||||
|
||||
/* Internal context for instrumenting an instruction */
|
||||
struct qemu_plugin_insn {
|
||||
uint64_t vaddr;
|
||||
GArray *insn_cbs;
|
||||
GArray *mem_cbs;
|
||||
uint8_t len;
|
||||
bool calls_helpers;
|
||||
|
||||
/* if set, the instruction calls helpers that might access guest memory */
|
||||
bool mem_helper;
|
||||
};
|
||||
|
||||
/* A scoreboard is an array of values, indexed by vcpu_index */
|
||||
struct qemu_plugin_scoreboard {
|
||||
GArray *data;
|
||||
QLIST_ENTRY(qemu_plugin_scoreboard) entry;
|
||||
};
|
||||
|
||||
/* Internal context for this TranslationBlock */
|
||||
struct qemu_plugin_tb {
|
||||
GPtrArray *insns;
|
||||
size_t n;
|
||||
|
||||
/* if set, the TB calls helpers that might access guest memory */
|
||||
bool mem_helper;
|
||||
|
||||
GArray *cbs;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct CPUPluginState - per-CPU state for plugins
|
||||
* @event_mask: plugin event bitmap. Modified only via async work.
|
||||
*/
|
||||
struct CPUPluginState {
|
||||
DECLARE_BITMAP(event_mask, QEMU_PLUGIN_EV_MAX);
|
||||
};
|
||||
|
||||
/**
|
||||
* qemu_plugin_create_vcpu_state: allocate plugin state
|
||||
*
|
||||
* The returned data must be released with g_free()
|
||||
* when no longer required.
|
||||
*/
|
||||
CPUPluginState *qemu_plugin_create_vcpu_state(void);
|
||||
|
||||
void qemu_plugin_vcpu_init_hook(CPUState *cpu);
|
||||
void qemu_plugin_vcpu_exit_hook(CPUState *cpu);
|
||||
void qemu_plugin_tb_trans_cb(CPUState *cpu, struct qemu_plugin_tb *tb);
|
||||
void qemu_plugin_vcpu_idle_cb(CPUState *cpu);
|
||||
void qemu_plugin_vcpu_resume_cb(CPUState *cpu);
|
||||
void qemu_plugin_vcpu_interrupt_cb(CPUState *cpu, uint64_t from);
|
||||
void qemu_plugin_vcpu_exception_cb(CPUState *cpu, uint64_t from);
|
||||
void qemu_plugin_vcpu_hostcall_cb(CPUState *cpu, uint64_t from);
|
||||
void
|
||||
qemu_plugin_vcpu_syscall(CPUState *cpu, int64_t num, uint64_t a1,
|
||||
uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5,
|
||||
uint64_t a6, uint64_t a7, uint64_t a8);
|
||||
void qemu_plugin_vcpu_syscall_ret(CPUState *cpu, int64_t num, int64_t ret);
|
||||
bool
|
||||
qemu_plugin_vcpu_syscall_filter(CPUState *cpu, int64_t num, uint64_t a1,
|
||||
uint64_t a2, uint64_t a3, uint64_t a4,
|
||||
uint64_t a5, uint64_t a6, uint64_t a7,
|
||||
uint64_t a8, int64_t *sysret);
|
||||
|
||||
void qemu_plugin_vcpu_mem_cb(CPUState *cpu, uint64_t vaddr,
|
||||
uint64_t value_low,
|
||||
uint64_t value_high,
|
||||
MemOpIdx oi, enum qemu_plugin_mem_rw rw);
|
||||
|
||||
void qemu_plugin_flush_cb(void);
|
||||
|
||||
void qemu_plugin_atexit_cb(void);
|
||||
|
||||
void qemu_plugin_add_dyn_cb_arr(GArray *arr);
|
||||
|
||||
static inline void qemu_plugin_disable_mem_helpers(CPUState *cpu)
|
||||
{
|
||||
cpu->neg.plugin_mem_cbs = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* qemu_plugin_user_exit(): clean-up callbacks before calling exit callbacks
|
||||
*
|
||||
* This is a user-mode only helper that ensure we have fully cleared
|
||||
* callbacks from all threads before calling the exit callbacks. This
|
||||
* is so the plugins themselves don't have to jump through hoops to
|
||||
* guard against race conditions.
|
||||
*/
|
||||
void qemu_plugin_user_exit(void);
|
||||
|
||||
/**
|
||||
* qemu_plugin_user_prefork_lock(): take plugin lock before forking
|
||||
*
|
||||
* This is a user-mode only helper to take the internal plugin lock
|
||||
* before a fork event. This is ensure a consistent lock state
|
||||
*/
|
||||
void qemu_plugin_user_prefork_lock(void);
|
||||
|
||||
/**
|
||||
* qemu_plugin_user_postfork(): reset the plugin lock
|
||||
* @is_child: is this thread the child
|
||||
*
|
||||
* This user-mode only helper resets the lock state after a fork so we
|
||||
* can continue using the plugin interface.
|
||||
*/
|
||||
void qemu_plugin_user_postfork(bool is_child);
|
||||
|
||||
enum qemu_plugin_cb_flags tcg_call_to_qemu_plugin_cb_flags(int flags);
|
||||
|
||||
static inline void qemu_plugin_set_cb_flags(CPUState *cpu,
|
||||
enum qemu_plugin_cb_flags flags)
|
||||
{
|
||||
assert(cpu);
|
||||
cpu->neg.plugin_cb_flags = flags;
|
||||
}
|
||||
|
||||
static inline enum qemu_plugin_cb_flags qemu_plugin_get_cb_flags(void)
|
||||
{
|
||||
assert(current_cpu);
|
||||
return current_cpu->neg.plugin_cb_flags;
|
||||
}
|
||||
|
||||
#else /* !CONFIG_PLUGIN */
|
||||
|
||||
static inline void qemu_plugin_add_opts(void)
|
||||
{ }
|
||||
|
||||
static inline void qemu_plugin_opt_parse(const char *optstr,
|
||||
QemuPluginList *head)
|
||||
{
|
||||
error_report("plugin interface not enabled in this build");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static inline int qemu_plugin_load_list(QemuPluginList *head, Error **errp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void qemu_plugin_vcpu_init_hook(CPUState *cpu)
|
||||
{ }
|
||||
|
||||
static inline void qemu_plugin_vcpu_exit_hook(CPUState *cpu)
|
||||
{ }
|
||||
|
||||
static inline void qemu_plugin_tb_trans_cb(CPUState *cpu,
|
||||
struct qemu_plugin_tb *tb)
|
||||
{ }
|
||||
|
||||
static inline void qemu_plugin_vcpu_idle_cb(CPUState *cpu)
|
||||
{ }
|
||||
|
||||
static inline void qemu_plugin_vcpu_resume_cb(CPUState *cpu)
|
||||
{ }
|
||||
|
||||
static inline void qemu_plugin_vcpu_interrupt_cb(CPUState *cpu, uint64_t from)
|
||||
{ }
|
||||
|
||||
static inline void qemu_plugin_vcpu_exception_cb(CPUState *cpu, uint64_t from)
|
||||
{ }
|
||||
|
||||
static inline void qemu_plugin_vcpu_hostcall_cb(CPUState *cpu, uint64_t from)
|
||||
{ }
|
||||
|
||||
static inline void
|
||||
qemu_plugin_vcpu_syscall(CPUState *cpu, int64_t num, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6,
|
||||
uint64_t a7, uint64_t a8)
|
||||
{ }
|
||||
|
||||
static inline
|
||||
void qemu_plugin_vcpu_syscall_ret(CPUState *cpu, int64_t num, int64_t ret)
|
||||
{ }
|
||||
|
||||
static inline bool
|
||||
qemu_plugin_vcpu_syscall_filter(CPUState *cpu, int64_t num, uint64_t a1,
|
||||
uint64_t a2, uint64_t a3, uint64_t a4,
|
||||
uint64_t a5, uint64_t a6, uint64_t a7,
|
||||
uint64_t a8, int64_t *sysret)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void qemu_plugin_vcpu_mem_cb(CPUState *cpu, uint64_t vaddr,
|
||||
uint64_t value_low,
|
||||
uint64_t value_high,
|
||||
MemOpIdx oi,
|
||||
enum qemu_plugin_mem_rw rw)
|
||||
{ }
|
||||
|
||||
static inline void qemu_plugin_flush_cb(void)
|
||||
{ }
|
||||
|
||||
static inline void qemu_plugin_atexit_cb(void)
|
||||
{ }
|
||||
|
||||
static inline
|
||||
void qemu_plugin_add_dyn_cb_arr(GArray *arr)
|
||||
{ }
|
||||
|
||||
static inline void qemu_plugin_disable_mem_helpers(CPUState *cpu)
|
||||
{ }
|
||||
|
||||
static inline void qemu_plugin_user_exit(void)
|
||||
{ }
|
||||
|
||||
static inline void qemu_plugin_user_prefork_lock(void)
|
||||
{ }
|
||||
|
||||
static inline void qemu_plugin_user_postfork(bool is_child)
|
||||
{ }
|
||||
|
||||
#endif /* !CONFIG_PLUGIN */
|
||||
|
||||
#endif /* QEMU_PLUGIN_H */
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* QEMU header file for libpmem.
|
||||
*
|
||||
* Copyright (c) 2018 Intel Corporation.
|
||||
*
|
||||
* Author: Haozhong Zhang <address@hidden>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_PMEM_H
|
||||
#define QEMU_PMEM_H
|
||||
|
||||
#ifdef CONFIG_LIBPMEM
|
||||
#include <libpmem.h>
|
||||
#else /* !CONFIG_LIBPMEM */
|
||||
|
||||
static inline void *
|
||||
pmem_memcpy_persist(void *pmemdest, const void *src, size_t len)
|
||||
{
|
||||
/* If 'pmem' option is 'on', we should always have libpmem support,
|
||||
or qemu will report a error and exit, never come here. */
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
static inline void
|
||||
pmem_persist(const void *addr, size_t len)
|
||||
{
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
#endif /* CONFIG_LIBPMEM */
|
||||
|
||||
#endif /* QEMU_PMEM_H */
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2016, Emilio G. Cota <[email protected]>
|
||||
*
|
||||
* License: GNU GPL, version 2.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
#ifndef QEMU_PROCESSOR_H
|
||||
#define QEMU_PROCESSOR_H
|
||||
|
||||
#if defined(__x86_64__)
|
||||
# define cpu_relax() asm volatile("rep; nop" ::: "memory")
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
# define cpu_relax() asm volatile("yield" ::: "memory")
|
||||
|
||||
#elif defined(__powerpc64__)
|
||||
/* set Hardware Multi-Threading (HMT) priority to low; then back to medium */
|
||||
# define cpu_relax() asm volatile("or 1, 1, 1;" \
|
||||
"or 2, 2, 2;" ::: "memory")
|
||||
|
||||
#else
|
||||
# define cpu_relax() barrier()
|
||||
#endif
|
||||
|
||||
#endif /* QEMU_PROCESSOR_H */
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Helper functionality for some process progress tracking.
|
||||
*
|
||||
* Copyright (c) 2011 IBM Corp.
|
||||
* Copyright (c) 2012, 2018 Red Hat, Inc.
|
||||
* Copyright (c) 2020 Virtuozzo International GmbH
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_PROGRESS_METER_H
|
||||
#define QEMU_PROGRESS_METER_H
|
||||
|
||||
#include "qemu/thread.h"
|
||||
|
||||
typedef struct ProgressMeter {
|
||||
/**
|
||||
* Current progress. The unit is arbitrary as long as the ratio between
|
||||
* current and total represents the estimated percentage
|
||||
* of work already done.
|
||||
*/
|
||||
uint64_t current;
|
||||
|
||||
/** Estimated current value at the completion of the process */
|
||||
uint64_t total;
|
||||
|
||||
QemuMutex lock; /* protects concurrent access to above fields */
|
||||
} ProgressMeter;
|
||||
|
||||
void progress_init(ProgressMeter *pm);
|
||||
void progress_destroy(ProgressMeter *pm);
|
||||
|
||||
/* Get a snapshot of internal current and total values */
|
||||
void progress_get_snapshot(ProgressMeter *pm, uint64_t *current,
|
||||
uint64_t *total);
|
||||
|
||||
/* Increases the amount of work done so far by @done */
|
||||
void progress_work_done(ProgressMeter *pm, uint64_t done);
|
||||
|
||||
/* Sets how much work has to be done to complete to @remaining */
|
||||
void progress_set_remaining(ProgressMeter *pm, uint64_t remaining);
|
||||
|
||||
/* Increases the total work to do by @delta */
|
||||
void progress_increase_remaining(ProgressMeter *pm, uint64_t delta);
|
||||
|
||||
#endif /* QEMU_PROGRESS_METER_H */
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (C) 2016, Emilio G. Cota <[email protected]>
|
||||
*
|
||||
* License: GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
#ifndef QEMU_QDIST_H
|
||||
#define QEMU_QDIST_H
|
||||
|
||||
#include "qemu/bitops.h"
|
||||
|
||||
/*
|
||||
* Samples with the same 'x value' end up in the same qdist_entry,
|
||||
* e.g. inc(0.1) and inc(0.1) end up as {x=0.1, count=2}.
|
||||
*
|
||||
* Binning happens only at print time, so that we retain the flexibility to
|
||||
* choose the binning. This might not be ideal for workloads that do not care
|
||||
* much about precision and insert many samples all with different x values;
|
||||
* in that case, pre-binning (e.g. entering both 0.115 and 0.097 as 0.1)
|
||||
* should be considered.
|
||||
*/
|
||||
struct qdist_entry {
|
||||
double x;
|
||||
unsigned long count;
|
||||
};
|
||||
|
||||
struct qdist {
|
||||
struct qdist_entry *entries;
|
||||
size_t n;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
#define QDIST_PR_BORDER BIT(0)
|
||||
#define QDIST_PR_LABELS BIT(1)
|
||||
/* the remaining options only work if PR_LABELS is set */
|
||||
#define QDIST_PR_NODECIMAL BIT(2)
|
||||
#define QDIST_PR_PERCENT BIT(3)
|
||||
#define QDIST_PR_100X BIT(4)
|
||||
#define QDIST_PR_NOBINRANGE BIT(5)
|
||||
|
||||
void qdist_init(struct qdist *dist);
|
||||
void qdist_destroy(struct qdist *dist);
|
||||
|
||||
void qdist_add(struct qdist *dist, double x, long count);
|
||||
void qdist_inc(struct qdist *dist, double x);
|
||||
double qdist_xmin(const struct qdist *dist);
|
||||
double qdist_xmax(const struct qdist *dist);
|
||||
double qdist_avg(const struct qdist *dist);
|
||||
unsigned long qdist_sample_count(const struct qdist *dist);
|
||||
size_t qdist_unique_entries(const struct qdist *dist);
|
||||
|
||||
/* callers must free the returned string with g_free() */
|
||||
char *qdist_pr_plain(const struct qdist *dist, size_t n_groups);
|
||||
|
||||
/* callers must free the returned string with g_free() */
|
||||
char *qdist_pr(const struct qdist *dist, size_t n_groups, uint32_t opt);
|
||||
|
||||
/* Only qdist code and test code should ever call this function */
|
||||
void qdist_bin__internal(struct qdist *to, const struct qdist *from, size_t n);
|
||||
|
||||
#endif /* QEMU_QDIST_H */
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Print to stream or current monitor
|
||||
*
|
||||
* Copyright (C) 2019 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Markus Armbruster <[email protected]>,
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_PRINT_H
|
||||
#define QEMU_PRINT_H
|
||||
|
||||
int qemu_vprintf(const char *fmt, va_list ap) G_GNUC_PRINTF(1, 0);
|
||||
int qemu_printf(const char *fmt, ...) G_GNUC_PRINTF(1, 2);
|
||||
|
||||
int qemu_vfprintf(FILE *stream, const char *fmt, va_list ap)
|
||||
G_GNUC_PRINTF(2, 0);
|
||||
int qemu_fprintf(FILE *stream, const char *fmt, ...) G_GNUC_PRINTF(2, 3);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef QEMU_PROGRESS_H
|
||||
#define QEMU_PROGRESS_H
|
||||
|
||||
void qemu_progress_init(int enabled, float min_skip);
|
||||
void qemu_progress_end(void);
|
||||
void qemu_progress_print(float delta, int max);
|
||||
|
||||
#endif /* QEMU_PROGRESS_H */
|
||||
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright (C) 2016, Emilio G. Cota <[email protected]>
|
||||
*
|
||||
* License: GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
#ifndef QEMU_QHT_H
|
||||
#define QEMU_QHT_H
|
||||
|
||||
#include "qemu/seqlock.h"
|
||||
#include "qemu/thread.h"
|
||||
#include "qemu/qdist.h"
|
||||
|
||||
typedef bool (*qht_cmp_func_t)(const void *a, const void *b);
|
||||
|
||||
struct qht {
|
||||
struct qht_map *map;
|
||||
qht_cmp_func_t cmp;
|
||||
QemuMutex lock; /* serializes setters of ht->map */
|
||||
unsigned int mode;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct qht_stats - Statistics of a QHT
|
||||
* @head_buckets: number of head buckets
|
||||
* @used_head_buckets: number of non-empty head buckets
|
||||
* @entries: total number of entries
|
||||
* @chain: frequency distribution representing the number of buckets in each
|
||||
* chain, excluding empty chains.
|
||||
* @occupancy: frequency distribution representing chain occupancy rate.
|
||||
* Valid range: from 0.0 (empty) to 1.0 (full occupancy).
|
||||
*
|
||||
* An entry is a pointer-hash pair.
|
||||
* Each bucket can host several entries.
|
||||
* Chains are chains of buckets, whose first link is always a head bucket.
|
||||
*/
|
||||
struct qht_stats {
|
||||
size_t head_buckets;
|
||||
size_t used_head_buckets;
|
||||
size_t entries;
|
||||
struct qdist chain;
|
||||
struct qdist occupancy;
|
||||
};
|
||||
|
||||
typedef bool (*qht_lookup_func_t)(const void *obj, const void *userp);
|
||||
typedef void (*qht_iter_func_t)(void *p, uint32_t h, void *up);
|
||||
typedef bool (*qht_iter_bool_func_t)(void *p, uint32_t h, void *up);
|
||||
|
||||
#define QHT_MODE_AUTO_RESIZE 0x1 /* auto-resize when heavily loaded */
|
||||
#define QHT_MODE_RAW_MUTEXES 0x2 /* bypass the profiler (QSP) */
|
||||
|
||||
/**
|
||||
* qht_init - Initialize a QHT
|
||||
* @ht: QHT to be initialized
|
||||
* @cmp: default comparison function. Cannot be NULL.
|
||||
* @n_elems: number of entries the hash table should be optimized for.
|
||||
* @mode: bitmask with OR'ed QHT_MODE_*
|
||||
*/
|
||||
void qht_init(struct qht *ht, qht_cmp_func_t cmp, size_t n_elems,
|
||||
unsigned int mode);
|
||||
|
||||
/**
|
||||
* qht_destroy - destroy a previously initialized QHT
|
||||
* @ht: QHT to be destroyed
|
||||
*
|
||||
* Call only when there are no readers/writers left.
|
||||
*/
|
||||
void qht_destroy(struct qht *ht);
|
||||
|
||||
/**
|
||||
* qht_insert - Insert a pointer into the hash table
|
||||
* @ht: QHT to insert to
|
||||
* @p: pointer to be inserted
|
||||
* @hash: hash corresponding to @p
|
||||
* @existing: address where the pointer to an existing entry can be copied to
|
||||
*
|
||||
* Attempting to insert a NULL @p is a bug.
|
||||
* Inserting the same pointer @p with different @hash values is a bug.
|
||||
*
|
||||
* In case of successful operation, smp_wmb() is implied before the pointer is
|
||||
* inserted into the hash table.
|
||||
*
|
||||
* Returns true on success.
|
||||
* Returns false if there is an existing entry in the table that is equivalent
|
||||
* (i.e. ht->cmp matches and the hash is the same) to @p-@h. If @existing
|
||||
* is !NULL, a pointer to this existing entry is copied to it.
|
||||
*/
|
||||
bool qht_insert(struct qht *ht, void *p, uint32_t hash, void **existing);
|
||||
|
||||
/**
|
||||
* qht_lookup_custom - Look up a pointer using a custom comparison function.
|
||||
* @ht: QHT to be looked up
|
||||
* @userp: pointer to pass to @func
|
||||
* @hash: hash of the pointer to be looked up
|
||||
* @func: function to compare existing pointers against @userp
|
||||
*
|
||||
* Needs to be called under an RCU read-critical section.
|
||||
*
|
||||
* smp_read_barrier_depends() is implied before the call to @func.
|
||||
*
|
||||
* The user-provided @func compares pointers in QHT against @userp.
|
||||
* If the function returns true, a match has been found.
|
||||
*
|
||||
* Returns the corresponding pointer when a match is found.
|
||||
* Returns NULL otherwise.
|
||||
*/
|
||||
void *qht_lookup_custom(const struct qht *ht, const void *userp, uint32_t hash,
|
||||
qht_lookup_func_t func);
|
||||
|
||||
/**
|
||||
* qht_lookup - Look up a pointer in a QHT
|
||||
* @ht: QHT to be looked up
|
||||
* @userp: pointer to pass to the comparison function
|
||||
* @hash: hash of the pointer to be looked up
|
||||
*
|
||||
* Calls qht_lookup_custom() using @ht's default comparison function.
|
||||
*/
|
||||
void *qht_lookup(const struct qht *ht, const void *userp, uint32_t hash);
|
||||
|
||||
/**
|
||||
* qht_remove - remove a pointer from the hash table
|
||||
* @ht: QHT to remove from
|
||||
* @p: pointer to be removed
|
||||
* @hash: hash corresponding to @p
|
||||
*
|
||||
* Attempting to remove a NULL @p is a bug.
|
||||
*
|
||||
* Just-removed @p pointers cannot be immediately freed; they need to remain
|
||||
* valid until the end of the RCU grace period in which qht_remove() is called.
|
||||
* This guarantees that concurrent lookups will always compare against valid
|
||||
* data.
|
||||
*
|
||||
* Returns true on success.
|
||||
* Returns false if the @p-@hash pair was not found.
|
||||
*/
|
||||
bool qht_remove(struct qht *ht, const void *p, uint32_t hash);
|
||||
|
||||
/**
|
||||
* qht_reset - reset a QHT
|
||||
* @ht: QHT to be reset
|
||||
*
|
||||
* All entries in the hash table are reset. No resizing is performed.
|
||||
*
|
||||
* If concurrent readers may exist, the objects pointed to by the hash table
|
||||
* must remain valid for the existing RCU grace period -- see qht_remove().
|
||||
* See also: qht_reset_size()
|
||||
*/
|
||||
void qht_reset(struct qht *ht);
|
||||
|
||||
/**
|
||||
* qht_reset_size - reset and resize a QHT
|
||||
* @ht: QHT to be reset and resized
|
||||
* @n_elems: number of entries the resized hash table should be optimized for.
|
||||
*
|
||||
* Returns true if the resize was necessary and therefore performed.
|
||||
* Returns false otherwise.
|
||||
*
|
||||
* If concurrent readers may exist, the objects pointed to by the hash table
|
||||
* must remain valid for the existing RCU grace period -- see qht_remove().
|
||||
* See also: qht_reset(), qht_resize().
|
||||
*/
|
||||
bool qht_reset_size(struct qht *ht, size_t n_elems);
|
||||
|
||||
/**
|
||||
* qht_resize - resize a QHT
|
||||
* @ht: QHT to be resized
|
||||
* @n_elems: number of entries the resized hash table should be optimized for
|
||||
*
|
||||
* Returns true on success.
|
||||
* Returns false if the resize was not necessary and therefore not performed.
|
||||
* See also: qht_reset_size().
|
||||
*/
|
||||
bool qht_resize(struct qht *ht, size_t n_elems);
|
||||
|
||||
/**
|
||||
* qht_iter - Iterate over a QHT
|
||||
* @ht: QHT to be iterated over
|
||||
* @func: function to be called for each entry in QHT
|
||||
* @userp: additional pointer to be passed to @func
|
||||
*
|
||||
* Each time it is called, user-provided @func is passed a pointer-hash pair,
|
||||
* plus @userp.
|
||||
*
|
||||
* Note: @ht cannot be accessed from @func
|
||||
* See also: qht_iter_remove()
|
||||
*/
|
||||
void qht_iter(struct qht *ht, qht_iter_func_t func, void *userp);
|
||||
|
||||
/**
|
||||
* qht_iter_remove - Iterate over a QHT, optionally removing entries
|
||||
* @ht: QHT to be iterated over
|
||||
* @func: function to be called for each entry in QHT
|
||||
* @userp: additional pointer to be passed to @func
|
||||
*
|
||||
* Each time it is called, user-provided @func is passed a pointer-hash pair,
|
||||
* plus @userp. If @func returns true, the pointer-hash pair is removed.
|
||||
*
|
||||
* Note: @ht cannot be accessed from @func
|
||||
* See also: qht_iter()
|
||||
*/
|
||||
void qht_iter_remove(struct qht *ht, qht_iter_bool_func_t func, void *userp);
|
||||
|
||||
/**
|
||||
* qht_statistics_init - Gather statistics from a QHT
|
||||
* @ht: QHT to gather statistics from
|
||||
* @stats: pointer to a &struct qht_stats to be filled in
|
||||
*
|
||||
* Does NOT need to be called under an RCU read-critical section,
|
||||
* since it does not dereference any pointers stored in the hash table.
|
||||
*
|
||||
* When done with @stats, pass the struct to qht_statistics_destroy().
|
||||
* Failing to do this will leak memory.
|
||||
*/
|
||||
void qht_statistics_init(const struct qht *ht, struct qht_stats *stats);
|
||||
|
||||
/**
|
||||
* qht_statistics_destroy - Destroy a &struct qht_stats
|
||||
* @stats: &struct qht_stats to be destroyed
|
||||
*
|
||||
* See also: qht_statistics_init().
|
||||
*/
|
||||
void qht_statistics_destroy(struct qht_stats *stats);
|
||||
|
||||
#endif /* QEMU_QHT_H */
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* qsp.c - QEMU Synchronization Profiler
|
||||
*
|
||||
* Copyright (C) 2018, Emilio G. Cota <[email protected]>
|
||||
*
|
||||
* License: GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
* Note: this header file can *only* be included from thread.h.
|
||||
*/
|
||||
#ifndef QEMU_QSP_H
|
||||
#define QEMU_QSP_H
|
||||
|
||||
enum QSPSortBy {
|
||||
QSP_SORT_BY_TOTAL_WAIT_TIME,
|
||||
QSP_SORT_BY_AVG_WAIT_TIME,
|
||||
};
|
||||
|
||||
void qsp_report(size_t max, enum QSPSortBy sort_by,
|
||||
bool callsite_coalesce);
|
||||
|
||||
bool qsp_is_enabled(void);
|
||||
void qsp_enable(void);
|
||||
void qsp_disable(void);
|
||||
void qsp_reset(void);
|
||||
|
||||
#endif /* QEMU_QSP_H */
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* QTree is a partial import of Glib's GTree. The parts excluded correspond
|
||||
* to API calls either deprecated (e.g. g_tree_traverse) or recently added
|
||||
* (e.g. g_tree_search_node, added in 2.68); neither have callers in QEMU.
|
||||
*
|
||||
* The reason for this import is to allow us to control the memory allocator
|
||||
* used by the tree implementation. Until Glib 2.75.3, GTree uses Glib's
|
||||
* slice allocator, which causes problems when forking in user-mode;
|
||||
* see https://gitlab.com/qemu-project/qemu/-/issues/285 and glib's
|
||||
* "45b5a6c1e gslice: Remove slice allocator and use malloc() instead".
|
||||
*
|
||||
* TODO: remove QTree when QEMU's minimum Glib version is >= 2.75.3.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_QTREE_H
|
||||
#define QEMU_QTREE_H
|
||||
|
||||
|
||||
#ifdef HAVE_GLIB_WITH_SLICE_ALLOCATOR
|
||||
|
||||
typedef struct _QTree QTree;
|
||||
|
||||
typedef struct _QTreeNode QTreeNode;
|
||||
|
||||
typedef gboolean (*QTraverseNodeFunc)(QTreeNode *node,
|
||||
gpointer user_data);
|
||||
|
||||
/*
|
||||
* Balanced binary trees
|
||||
*/
|
||||
QTree *q_tree_new(GCompareFunc key_compare_func);
|
||||
QTree *q_tree_new_with_data(GCompareDataFunc key_compare_func,
|
||||
gpointer key_compare_data);
|
||||
QTree *q_tree_new_full(GCompareDataFunc key_compare_func,
|
||||
gpointer key_compare_data,
|
||||
GDestroyNotify key_destroy_func,
|
||||
GDestroyNotify value_destroy_func);
|
||||
QTree *q_tree_ref(QTree *tree);
|
||||
void q_tree_unref(QTree *tree);
|
||||
void q_tree_destroy(QTree *tree);
|
||||
void q_tree_insert(QTree *tree,
|
||||
gpointer key,
|
||||
gpointer value);
|
||||
void q_tree_replace(QTree *tree,
|
||||
gpointer key,
|
||||
gpointer value);
|
||||
gboolean q_tree_remove(QTree *tree,
|
||||
gconstpointer key);
|
||||
gboolean q_tree_steal(QTree *tree,
|
||||
gconstpointer key);
|
||||
gpointer q_tree_lookup(QTree *tree,
|
||||
gconstpointer key);
|
||||
gboolean q_tree_lookup_extended(QTree *tree,
|
||||
gconstpointer lookup_key,
|
||||
gpointer *orig_key,
|
||||
gpointer *value);
|
||||
void q_tree_foreach(QTree *tree,
|
||||
GTraverseFunc func,
|
||||
gpointer user_data);
|
||||
gpointer q_tree_search(QTree *tree,
|
||||
GCompareFunc search_func,
|
||||
gconstpointer user_data);
|
||||
gint q_tree_height(QTree *tree);
|
||||
gint q_tree_nnodes(QTree *tree);
|
||||
|
||||
#else /* !HAVE_GLIB_WITH_SLICE_ALLOCATOR */
|
||||
|
||||
typedef GTree QTree;
|
||||
typedef GTreeNode QTreeNode;
|
||||
typedef GTraverseNodeFunc QTraverseNodeFunc;
|
||||
|
||||
static inline QTree *q_tree_new(GCompareFunc key_compare_func)
|
||||
{
|
||||
return g_tree_new(key_compare_func);
|
||||
}
|
||||
|
||||
static inline QTree *q_tree_new_with_data(GCompareDataFunc key_compare_func,
|
||||
gpointer key_compare_data)
|
||||
{
|
||||
return g_tree_new_with_data(key_compare_func, key_compare_data);
|
||||
}
|
||||
|
||||
static inline QTree *q_tree_new_full(GCompareDataFunc key_compare_func,
|
||||
gpointer key_compare_data,
|
||||
GDestroyNotify key_destroy_func,
|
||||
GDestroyNotify value_destroy_func)
|
||||
{
|
||||
return g_tree_new_full(key_compare_func, key_compare_data,
|
||||
key_destroy_func, value_destroy_func);
|
||||
}
|
||||
|
||||
static inline QTree *q_tree_ref(QTree *tree)
|
||||
{
|
||||
return g_tree_ref(tree);
|
||||
}
|
||||
|
||||
static inline void q_tree_unref(QTree *tree)
|
||||
{
|
||||
g_tree_unref(tree);
|
||||
}
|
||||
|
||||
static inline void q_tree_destroy(QTree *tree)
|
||||
{
|
||||
g_tree_destroy(tree);
|
||||
}
|
||||
|
||||
static inline void q_tree_insert(QTree *tree,
|
||||
gpointer key,
|
||||
gpointer value)
|
||||
{
|
||||
g_tree_insert(tree, key, value);
|
||||
}
|
||||
|
||||
static inline void q_tree_replace(QTree *tree,
|
||||
gpointer key,
|
||||
gpointer value)
|
||||
{
|
||||
g_tree_replace(tree, key, value);
|
||||
}
|
||||
|
||||
static inline gboolean q_tree_remove(QTree *tree,
|
||||
gconstpointer key)
|
||||
{
|
||||
return g_tree_remove(tree, key);
|
||||
}
|
||||
|
||||
static inline gboolean q_tree_steal(QTree *tree,
|
||||
gconstpointer key)
|
||||
{
|
||||
return g_tree_steal(tree, key);
|
||||
}
|
||||
|
||||
static inline gpointer q_tree_lookup(QTree *tree,
|
||||
gconstpointer key)
|
||||
{
|
||||
return g_tree_lookup(tree, key);
|
||||
}
|
||||
|
||||
static inline gboolean q_tree_lookup_extended(QTree *tree,
|
||||
gconstpointer lookup_key,
|
||||
gpointer *orig_key,
|
||||
gpointer *value)
|
||||
{
|
||||
return g_tree_lookup_extended(tree, lookup_key, orig_key, value);
|
||||
}
|
||||
|
||||
static inline void q_tree_foreach(QTree *tree,
|
||||
GTraverseFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
return g_tree_foreach(tree, func, user_data);
|
||||
}
|
||||
|
||||
static inline gpointer q_tree_search(QTree *tree,
|
||||
GCompareFunc search_func,
|
||||
gconstpointer user_data)
|
||||
{
|
||||
return g_tree_search(tree, search_func, user_data);
|
||||
}
|
||||
|
||||
static inline gint q_tree_height(QTree *tree)
|
||||
{
|
||||
return g_tree_height(tree);
|
||||
}
|
||||
|
||||
static inline gint q_tree_nnodes(QTree *tree)
|
||||
{
|
||||
return g_tree_nnodes(tree);
|
||||
}
|
||||
|
||||
#endif /* HAVE_GLIB_WITH_SLICE_ALLOCATOR */
|
||||
|
||||
#endif /* QEMU_QTREE_H */
|
||||
@@ -0,0 +1,576 @@
|
||||
/* $NetBSD: queue.h,v 1.52 2009/04/20 09:56:08 mschuett Exp $ */
|
||||
|
||||
/*
|
||||
* QEMU version: Copy from netbsd, removed debug code, removed some of
|
||||
* the implementations. Left in singly-linked lists, lists, simple
|
||||
* queues, and tail queues.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)queue.h 8.5 (Berkeley) 8/20/94
|
||||
*/
|
||||
|
||||
#ifndef QEMU_SYS_QUEUE_H
|
||||
#define QEMU_SYS_QUEUE_H
|
||||
|
||||
/*
|
||||
* This file defines four types of data structures: singly-linked lists,
|
||||
* lists, simple queues, and tail queues.
|
||||
*
|
||||
* A singly-linked list is headed by a single forward pointer. The
|
||||
* elements are singly linked for minimum space and pointer manipulation
|
||||
* overhead at the expense of O(n) removal for arbitrary elements. New
|
||||
* elements can be added to the list after an existing element or at the
|
||||
* head of the list. Elements being removed from the head of the list
|
||||
* should use the explicit macro for this purpose for optimum
|
||||
* efficiency. A singly-linked list may only be traversed in the forward
|
||||
* direction. Singly-linked lists are ideal for applications with large
|
||||
* datasets and few or no removals or for implementing a LIFO queue.
|
||||
*
|
||||
* A list is headed by a single forward pointer (or an array of forward
|
||||
* pointers for a hash table header). The elements are doubly linked
|
||||
* so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before
|
||||
* or after an existing element or at the head of the list. A list
|
||||
* may only be traversed in the forward direction.
|
||||
*
|
||||
* A simple queue is headed by a pair of pointers, one the head of the
|
||||
* list and the other to the tail of the list. The elements are singly
|
||||
* linked to save space, so elements can only be removed from the
|
||||
* head of the list. New elements can be added to the list after
|
||||
* an existing element, at the head of the list, or at the end of the
|
||||
* list. A simple queue may only be traversed in the forward direction.
|
||||
*
|
||||
* A tail queue is headed by a pair of pointers, one to the head of the
|
||||
* list and the other to the tail of the list. The elements are doubly
|
||||
* linked so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before or
|
||||
* after an existing element, at the head of the list, or at the end of
|
||||
* the list. A tail queue may be traversed in either direction.
|
||||
*
|
||||
* For details on the use of these macros, see the queue(3) manual page.
|
||||
*/
|
||||
|
||||
/*
|
||||
* List definitions.
|
||||
*/
|
||||
#define QLIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *lh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define QLIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#define QLIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *le_next; /* next element */ \
|
||||
struct type **le_prev; /* address of previous next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* List functions.
|
||||
*/
|
||||
#define QLIST_INIT(head) do { \
|
||||
(head)->lh_first = NULL; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QLIST_SWAP(dstlist, srclist, field) do { \
|
||||
void *tmplist; \
|
||||
tmplist = (srclist)->lh_first; \
|
||||
(srclist)->lh_first = (dstlist)->lh_first; \
|
||||
if ((srclist)->lh_first != NULL) { \
|
||||
(srclist)->lh_first->field.le_prev = &(srclist)->lh_first; \
|
||||
} \
|
||||
(dstlist)->lh_first = tmplist; \
|
||||
if ((dstlist)->lh_first != NULL) { \
|
||||
(dstlist)->lh_first->field.le_prev = &(dstlist)->lh_first; \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QLIST_INSERT_AFTER(listelm, elm, field) do { \
|
||||
if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
|
||||
(listelm)->field.le_next->field.le_prev = \
|
||||
&(elm)->field.le_next; \
|
||||
(listelm)->field.le_next = (elm); \
|
||||
(elm)->field.le_prev = &(listelm)->field.le_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QLIST_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
(elm)->field.le_prev = (listelm)->field.le_prev; \
|
||||
(elm)->field.le_next = (listelm); \
|
||||
*(listelm)->field.le_prev = (elm); \
|
||||
(listelm)->field.le_prev = &(elm)->field.le_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QLIST_INSERT_HEAD(head, elm, field) do { \
|
||||
if (((elm)->field.le_next = (head)->lh_first) != NULL) \
|
||||
(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
|
||||
(head)->lh_first = (elm); \
|
||||
(elm)->field.le_prev = &(head)->lh_first; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QLIST_REMOVE(elm, field) do { \
|
||||
if ((elm)->field.le_next != NULL) \
|
||||
(elm)->field.le_next->field.le_prev = \
|
||||
(elm)->field.le_prev; \
|
||||
*(elm)->field.le_prev = (elm)->field.le_next; \
|
||||
(elm)->field.le_next = NULL; \
|
||||
(elm)->field.le_prev = NULL; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/*
|
||||
* Like QLIST_REMOVE() but safe to call when elm is not in a list
|
||||
*/
|
||||
#define QLIST_SAFE_REMOVE(elm, field) do { \
|
||||
if ((elm)->field.le_prev != NULL) { \
|
||||
if ((elm)->field.le_next != NULL) \
|
||||
(elm)->field.le_next->field.le_prev = \
|
||||
(elm)->field.le_prev; \
|
||||
*(elm)->field.le_prev = (elm)->field.le_next; \
|
||||
(elm)->field.le_next = NULL; \
|
||||
(elm)->field.le_prev = NULL; \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/* Is elm in a list? */
|
||||
#define QLIST_IS_INSERTED(elm, field) ((elm)->field.le_prev != NULL)
|
||||
|
||||
#define QLIST_FOREACH(var, head, field) \
|
||||
for ((var) = ((head)->lh_first); \
|
||||
(var); \
|
||||
(var) = ((var)->field.le_next))
|
||||
|
||||
#define QLIST_FOREACH_SAFE(var, head, field, next_var) \
|
||||
for ((var) = ((head)->lh_first); \
|
||||
(var) && ((next_var) = ((var)->field.le_next), 1); \
|
||||
(var) = (next_var))
|
||||
|
||||
/*
|
||||
* List access methods.
|
||||
*/
|
||||
#define QLIST_EMPTY(head) ((head)->lh_first == NULL)
|
||||
#define QLIST_FIRST(head) ((head)->lh_first)
|
||||
#define QLIST_NEXT(elm, field) ((elm)->field.le_next)
|
||||
|
||||
|
||||
/*
|
||||
* Singly-linked List definitions.
|
||||
*/
|
||||
#define QSLIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *slh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define QSLIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#define QSLIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *sle_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Singly-linked List functions.
|
||||
*/
|
||||
#define QSLIST_INIT(head) do { \
|
||||
(head)->slh_first = NULL; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSLIST_INSERT_AFTER(slistelm, elm, field) do { \
|
||||
(elm)->field.sle_next = (slistelm)->field.sle_next; \
|
||||
(slistelm)->field.sle_next = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSLIST_INSERT_HEAD(head, elm, field) do { \
|
||||
(elm)->field.sle_next = (head)->slh_first; \
|
||||
(head)->slh_first = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSLIST_INSERT_HEAD_ATOMIC(head, elm, field) do { \
|
||||
typeof(elm) save_sle_next; \
|
||||
do { \
|
||||
save_sle_next = (elm)->field.sle_next = (head)->slh_first; \
|
||||
} while (qatomic_cmpxchg(&(head)->slh_first, save_sle_next, (elm)) !=\
|
||||
save_sle_next); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSLIST_MOVE_ATOMIC(dest, src) do { \
|
||||
(dest)->slh_first = qatomic_xchg(&(src)->slh_first, NULL); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSLIST_REMOVE_HEAD(head, field) do { \
|
||||
typeof((head)->slh_first) elm = (head)->slh_first; \
|
||||
(head)->slh_first = elm->field.sle_next; \
|
||||
elm->field.sle_next = NULL; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSLIST_REMOVE_AFTER(slistelm, field) do { \
|
||||
typeof(slistelm) next = (slistelm)->field.sle_next; \
|
||||
(slistelm)->field.sle_next = next->field.sle_next; \
|
||||
next->field.sle_next = NULL; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSLIST_REMOVE(head, elm, type, field) do { \
|
||||
if ((head)->slh_first == (elm)) { \
|
||||
QSLIST_REMOVE_HEAD((head), field); \
|
||||
} else { \
|
||||
struct type *curelm = (head)->slh_first; \
|
||||
while (curelm->field.sle_next != (elm)) \
|
||||
curelm = curelm->field.sle_next; \
|
||||
curelm->field.sle_next = curelm->field.sle_next->field.sle_next; \
|
||||
(elm)->field.sle_next = NULL; \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSLIST_FOREACH(var, head, field) \
|
||||
for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)
|
||||
|
||||
#define QSLIST_FOREACH_SAFE(var, head, field, tvar) \
|
||||
for ((var) = QSLIST_FIRST((head)); \
|
||||
(var) && ((tvar) = QSLIST_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
/*
|
||||
* Singly-linked List access methods.
|
||||
*/
|
||||
#define QSLIST_EMPTY(head) ((head)->slh_first == NULL)
|
||||
#define QSLIST_FIRST(head) ((head)->slh_first)
|
||||
#define QSLIST_NEXT(elm, field) ((elm)->field.sle_next)
|
||||
|
||||
|
||||
/*
|
||||
* Simple queue definitions.
|
||||
*/
|
||||
#define QSIMPLEQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *sqh_first; /* first element */ \
|
||||
struct type **sqh_last; /* addr of last next element */ \
|
||||
}
|
||||
|
||||
#define QSIMPLEQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).sqh_first }
|
||||
|
||||
#define QSIMPLEQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *sqe_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple queue functions.
|
||||
*/
|
||||
#define QSIMPLEQ_INIT(head) do { \
|
||||
(head)->sqh_first = NULL; \
|
||||
(head)->sqh_last = &(head)->sqh_first; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSIMPLEQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
|
||||
(head)->sqh_last = &(elm)->field.sqe_next; \
|
||||
(head)->sqh_first = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSIMPLEQ_INSERT_TAIL(head, elm, field) do { \
|
||||
(elm)->field.sqe_next = NULL; \
|
||||
*(head)->sqh_last = (elm); \
|
||||
(head)->sqh_last = &(elm)->field.sqe_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL) \
|
||||
(head)->sqh_last = &(elm)->field.sqe_next; \
|
||||
(listelm)->field.sqe_next = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSIMPLEQ_REMOVE_HEAD(head, field) do { \
|
||||
typeof((head)->sqh_first) elm = (head)->sqh_first; \
|
||||
if (((head)->sqh_first = elm->field.sqe_next) == NULL) \
|
||||
(head)->sqh_last = &(head)->sqh_first; \
|
||||
elm->field.sqe_next = NULL; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSIMPLEQ_SPLIT_AFTER(head, elm, field, removed) do { \
|
||||
QSIMPLEQ_INIT(removed); \
|
||||
if (((removed)->sqh_first = (head)->sqh_first) != NULL) { \
|
||||
if (((head)->sqh_first = (elm)->field.sqe_next) == NULL) { \
|
||||
(head)->sqh_last = &(head)->sqh_first; \
|
||||
} \
|
||||
(removed)->sqh_last = &(elm)->field.sqe_next; \
|
||||
(elm)->field.sqe_next = NULL; \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSIMPLEQ_REMOVE(head, elm, type, field) do { \
|
||||
if ((head)->sqh_first == (elm)) { \
|
||||
QSIMPLEQ_REMOVE_HEAD((head), field); \
|
||||
} else { \
|
||||
struct type *curelm = (head)->sqh_first; \
|
||||
while (curelm->field.sqe_next != (elm)) \
|
||||
curelm = curelm->field.sqe_next; \
|
||||
if ((curelm->field.sqe_next = \
|
||||
curelm->field.sqe_next->field.sqe_next) == NULL) \
|
||||
(head)->sqh_last = &(curelm)->field.sqe_next; \
|
||||
(elm)->field.sqe_next = NULL; \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSIMPLEQ_FOREACH(var, head, field) \
|
||||
for ((var) = ((head)->sqh_first); \
|
||||
(var); \
|
||||
(var) = ((var)->field.sqe_next))
|
||||
|
||||
#define QSIMPLEQ_FOREACH_SAFE(var, head, field, next) \
|
||||
for ((var) = ((head)->sqh_first); \
|
||||
(var) && ((next = ((var)->field.sqe_next)), 1); \
|
||||
(var) = (next))
|
||||
|
||||
#define QSIMPLEQ_CONCAT(head1, head2) do { \
|
||||
if (!QSIMPLEQ_EMPTY((head2))) { \
|
||||
*(head1)->sqh_last = (head2)->sqh_first; \
|
||||
(head1)->sqh_last = (head2)->sqh_last; \
|
||||
QSIMPLEQ_INIT((head2)); \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSIMPLEQ_PREPEND(head1, head2) do { \
|
||||
if (!QSIMPLEQ_EMPTY((head2))) { \
|
||||
*(head2)->sqh_last = (head1)->sqh_first; \
|
||||
(head1)->sqh_first = (head2)->sqh_first; \
|
||||
QSIMPLEQ_INIT((head2)); \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSIMPLEQ_LAST(head, type, field) \
|
||||
(QSIMPLEQ_EMPTY((head)) ? \
|
||||
NULL : \
|
||||
((struct type *)(void *) \
|
||||
((char *)((head)->sqh_last) - offsetof(struct type, field))))
|
||||
|
||||
/*
|
||||
* Simple queue access methods.
|
||||
*/
|
||||
#define QSIMPLEQ_EMPTY_ATOMIC(head) \
|
||||
(qatomic_read(&((head)->sqh_first)) == NULL)
|
||||
#define QSIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL)
|
||||
#define QSIMPLEQ_FIRST(head) ((head)->sqh_first)
|
||||
#define QSIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
|
||||
|
||||
typedef struct QTailQLink {
|
||||
void *tql_next;
|
||||
struct QTailQLink *tql_prev;
|
||||
} QTailQLink;
|
||||
|
||||
/*
|
||||
* Tail queue definitions. The union acts as a poor man template, as if
|
||||
* it were QTailQLink<type>.
|
||||
*/
|
||||
#define QTAILQ_HEAD(name, type) \
|
||||
union name { \
|
||||
struct type *tqh_first; /* first element */ \
|
||||
QTailQLink tqh_circ; /* link for circular backwards list */ \
|
||||
}
|
||||
|
||||
#define QTAILQ_HEAD_INITIALIZER(head) \
|
||||
{ .tqh_circ = { NULL, &(head).tqh_circ } }
|
||||
|
||||
#define QTAILQ_ENTRY(type) \
|
||||
union { \
|
||||
struct type *tqe_next; /* next element */ \
|
||||
QTailQLink tqe_circ; /* link for circular backwards list */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Tail queue functions.
|
||||
*/
|
||||
#define QTAILQ_INIT(head) do { \
|
||||
(head)->tqh_first = NULL; \
|
||||
(head)->tqh_circ.tql_prev = &(head)->tqh_circ; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QTAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
|
||||
(head)->tqh_first->field.tqe_circ.tql_prev = \
|
||||
&(elm)->field.tqe_circ; \
|
||||
else \
|
||||
(head)->tqh_circ.tql_prev = &(elm)->field.tqe_circ; \
|
||||
(head)->tqh_first = (elm); \
|
||||
(elm)->field.tqe_circ.tql_prev = &(head)->tqh_circ; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QTAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||
(elm)->field.tqe_next = NULL; \
|
||||
(elm)->field.tqe_circ.tql_prev = (head)->tqh_circ.tql_prev; \
|
||||
(head)->tqh_circ.tql_prev->tql_next = (elm); \
|
||||
(head)->tqh_circ.tql_prev = &(elm)->field.tqe_circ; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QTAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
|
||||
(elm)->field.tqe_next->field.tqe_circ.tql_prev = \
|
||||
&(elm)->field.tqe_circ; \
|
||||
else \
|
||||
(head)->tqh_circ.tql_prev = &(elm)->field.tqe_circ; \
|
||||
(listelm)->field.tqe_next = (elm); \
|
||||
(elm)->field.tqe_circ.tql_prev = &(listelm)->field.tqe_circ; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QTAILQ_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
(elm)->field.tqe_circ.tql_prev = (listelm)->field.tqe_circ.tql_prev; \
|
||||
(elm)->field.tqe_next = (listelm); \
|
||||
(listelm)->field.tqe_circ.tql_prev->tql_next = (elm); \
|
||||
(listelm)->field.tqe_circ.tql_prev = &(elm)->field.tqe_circ; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QTAILQ_REMOVE(head, elm, field) do { \
|
||||
if (((elm)->field.tqe_next) != NULL) \
|
||||
(elm)->field.tqe_next->field.tqe_circ.tql_prev = \
|
||||
(elm)->field.tqe_circ.tql_prev; \
|
||||
else \
|
||||
(head)->tqh_circ.tql_prev = (elm)->field.tqe_circ.tql_prev; \
|
||||
(elm)->field.tqe_circ.tql_prev->tql_next = (elm)->field.tqe_next; \
|
||||
(elm)->field.tqe_circ.tql_prev = NULL; \
|
||||
(elm)->field.tqe_circ.tql_next = NULL; \
|
||||
(elm)->field.tqe_next = NULL; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/* remove @left, @right and all elements in between from @head */
|
||||
#define QTAILQ_REMOVE_SEVERAL(head, left, right, field) do { \
|
||||
if (((right)->field.tqe_next) != NULL) \
|
||||
(right)->field.tqe_next->field.tqe_circ.tql_prev = \
|
||||
(left)->field.tqe_circ.tql_prev; \
|
||||
else \
|
||||
(head)->tqh_circ.tql_prev = (left)->field.tqe_circ.tql_prev; \
|
||||
(left)->field.tqe_circ.tql_prev->tql_next = (right)->field.tqe_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QTAILQ_FOREACH(var, head, field) \
|
||||
for ((var) = ((head)->tqh_first); \
|
||||
(var); \
|
||||
(var) = ((var)->field.tqe_next))
|
||||
|
||||
#define QTAILQ_FOREACH_SAFE(var, head, field, next_var) \
|
||||
for ((var) = ((head)->tqh_first); \
|
||||
(var) && ((next_var) = ((var)->field.tqe_next), 1); \
|
||||
(var) = (next_var))
|
||||
|
||||
#define QTAILQ_FOREACH_REVERSE(var, head, field) \
|
||||
for ((var) = QTAILQ_LAST(head); \
|
||||
(var); \
|
||||
(var) = QTAILQ_PREV(var, field))
|
||||
|
||||
#define QTAILQ_FOREACH_REVERSE_SAFE(var, head, field, prev_var) \
|
||||
for ((var) = QTAILQ_LAST(head); \
|
||||
(var) && ((prev_var) = QTAILQ_PREV(var, field), 1); \
|
||||
(var) = (prev_var))
|
||||
|
||||
/*
|
||||
* Tail queue access methods.
|
||||
*/
|
||||
#define QTAILQ_EMPTY(head) ((head)->tqh_first == NULL)
|
||||
#define QTAILQ_FIRST(head) ((head)->tqh_first)
|
||||
#define QTAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
|
||||
#define QTAILQ_IN_USE(elm, field) ((elm)->field.tqe_circ.tql_prev != NULL)
|
||||
|
||||
#define QTAILQ_LINK_PREV(link) \
|
||||
((link).tql_prev->tql_prev->tql_next)
|
||||
#define QTAILQ_LAST(head) \
|
||||
((typeof((head)->tqh_first)) QTAILQ_LINK_PREV((head)->tqh_circ))
|
||||
#define QTAILQ_PREV(elm, field) \
|
||||
((typeof((elm)->field.tqe_next)) QTAILQ_LINK_PREV((elm)->field.tqe_circ))
|
||||
|
||||
#define field_at_offset(base, offset, type) \
|
||||
((type *) (((char *) (base)) + (offset)))
|
||||
|
||||
/*
|
||||
* Raw access of elements of a tail queue head. Offsets are all zero
|
||||
* because it's a union.
|
||||
*/
|
||||
#define QTAILQ_RAW_FIRST(head) \
|
||||
field_at_offset(head, 0, void *)
|
||||
#define QTAILQ_RAW_TQH_CIRC(head) \
|
||||
field_at_offset(head, 0, QTailQLink)
|
||||
|
||||
/*
|
||||
* Raw access of elements of a tail entry
|
||||
*/
|
||||
#define QTAILQ_RAW_NEXT(elm, entry) \
|
||||
field_at_offset(elm, entry, void *)
|
||||
#define QTAILQ_RAW_TQE_CIRC(elm, entry) \
|
||||
field_at_offset(elm, entry, QTailQLink)
|
||||
/*
|
||||
* Tail queue traversal using pointer arithmetic.
|
||||
*/
|
||||
#define QTAILQ_RAW_FOREACH(elm, head, entry) \
|
||||
for ((elm) = *QTAILQ_RAW_FIRST(head); \
|
||||
(elm); \
|
||||
(elm) = *QTAILQ_RAW_NEXT(elm, entry))
|
||||
/*
|
||||
* Tail queue insertion using pointer arithmetic.
|
||||
*/
|
||||
#define QTAILQ_RAW_INSERT_TAIL(head, elm, entry) do { \
|
||||
*QTAILQ_RAW_NEXT(elm, entry) = NULL; \
|
||||
QTAILQ_RAW_TQE_CIRC(elm, entry)->tql_prev = QTAILQ_RAW_TQH_CIRC(head)->tql_prev; \
|
||||
QTAILQ_RAW_TQH_CIRC(head)->tql_prev->tql_next = (elm); \
|
||||
QTAILQ_RAW_TQH_CIRC(head)->tql_prev = QTAILQ_RAW_TQE_CIRC(elm, entry); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QLIST_RAW_FIRST(head) \
|
||||
field_at_offset(head, 0, void *)
|
||||
|
||||
#define QLIST_RAW_NEXT(elm, entry) \
|
||||
field_at_offset(elm, entry, void *)
|
||||
|
||||
#define QLIST_RAW_PREVIOUS(elm, entry) \
|
||||
field_at_offset(elm, entry + sizeof(void *), void *)
|
||||
|
||||
#define QLIST_RAW_FOREACH(elm, head, entry) \
|
||||
for ((elm) = *QLIST_RAW_FIRST(head); \
|
||||
(elm); \
|
||||
(elm) = *QLIST_RAW_NEXT(elm, entry))
|
||||
|
||||
#define QLIST_RAW_INSERT_AFTER(head, prev, elem, entry) do { \
|
||||
*QLIST_RAW_NEXT(prev, entry) = elem; \
|
||||
*QLIST_RAW_PREVIOUS(elem, entry) = QLIST_RAW_NEXT(prev, entry); \
|
||||
*QLIST_RAW_NEXT(elem, entry) = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define QLIST_RAW_INSERT_HEAD(head, elm, entry) do { \
|
||||
void *first = *QLIST_RAW_FIRST(head); \
|
||||
*QLIST_RAW_FIRST(head) = elm; \
|
||||
*QLIST_RAW_PREVIOUS(elm, entry) = QLIST_RAW_FIRST(head); \
|
||||
if (first) { \
|
||||
*QLIST_RAW_NEXT(elm, entry) = first; \
|
||||
*QLIST_RAW_PREVIOUS(first, entry) = QLIST_RAW_NEXT(elm, entry); \
|
||||
} else { \
|
||||
*QLIST_RAW_NEXT(elm, entry) = NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif /* QEMU_SYS_QUEUE_H */
|
||||
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* QEMU 64-bit address ranges
|
||||
*
|
||||
* Copyright (c) 2015-2016 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_RANGE_H
|
||||
#define QEMU_RANGE_H
|
||||
|
||||
#include "qemu/bitops.h"
|
||||
|
||||
/*
|
||||
* Operations on 64 bit address ranges.
|
||||
* Notes:
|
||||
* - Ranges must not wrap around 0, but can include UINT64_MAX.
|
||||
*/
|
||||
|
||||
struct Range {
|
||||
/*
|
||||
* Do not access members directly, use the functions!
|
||||
* A non-empty range has @lob <= @upb.
|
||||
* An empty range has @lob == @upb + 1.
|
||||
*/
|
||||
uint64_t lob; /* inclusive lower bound */
|
||||
uint64_t upb; /* inclusive upper bound */
|
||||
};
|
||||
|
||||
static inline void range_invariant(const Range *range)
|
||||
{
|
||||
assert(range->lob <= range->upb || range->lob == range->upb + 1);
|
||||
}
|
||||
|
||||
/* Compound literal encoding the empty range */
|
||||
#define range_empty ((Range){ .lob = 1, .upb = 0 })
|
||||
|
||||
/* Is @range empty? */
|
||||
static inline bool range_is_empty(const Range *range)
|
||||
{
|
||||
range_invariant(range);
|
||||
return range->lob > range->upb;
|
||||
}
|
||||
|
||||
/* Does @range contain @val? */
|
||||
static inline bool range_contains(const Range *range, uint64_t val)
|
||||
{
|
||||
return val >= range->lob && val <= range->upb;
|
||||
}
|
||||
|
||||
/* Initialize @range to the empty range */
|
||||
static inline void range_make_empty(Range *range)
|
||||
{
|
||||
*range = range_empty;
|
||||
assert(range_is_empty(range));
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize @range to span the interval [@lob,@upb].
|
||||
* Both bounds are inclusive.
|
||||
* The interval must not be empty, i.e. @lob must be less than or
|
||||
* equal @upb.
|
||||
*/
|
||||
static inline void range_set_bounds(Range *range, uint64_t lob, uint64_t upb)
|
||||
{
|
||||
range->lob = lob;
|
||||
range->upb = upb;
|
||||
assert(!range_is_empty(range));
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize @range to span the interval [@lob,@upb_plus1).
|
||||
* The lower bound is inclusive, the upper bound is exclusive.
|
||||
* Zero @upb_plus1 is special: if @lob is also zero, set @range to the
|
||||
* empty range. Else, set @range to [@lob,UINT64_MAX].
|
||||
*/
|
||||
static inline void range_set_bounds1(Range *range,
|
||||
uint64_t lob, uint64_t upb_plus1)
|
||||
{
|
||||
if (!lob && !upb_plus1) {
|
||||
*range = range_empty;
|
||||
} else {
|
||||
range->lob = lob;
|
||||
range->upb = upb_plus1 - 1;
|
||||
}
|
||||
range_invariant(range);
|
||||
}
|
||||
|
||||
/* Return @range's lower bound. @range must not be empty. */
|
||||
static inline uint64_t range_lob(Range *range)
|
||||
{
|
||||
assert(!range_is_empty(range));
|
||||
return range->lob;
|
||||
}
|
||||
|
||||
/* Return @range's upper bound. @range must not be empty. */
|
||||
static inline uint64_t range_upb(Range *range)
|
||||
{
|
||||
assert(!range_is_empty(range));
|
||||
return range->upb;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize @range to span the interval [@lob,@lob + @size - 1].
|
||||
* @size may be 0. If the range would overflow, returns -ERANGE, otherwise
|
||||
* 0.
|
||||
*/
|
||||
G_GNUC_WARN_UNUSED_RESULT
|
||||
static inline int range_init(Range *range, uint64_t lob, uint64_t size)
|
||||
{
|
||||
if (lob + size < lob) {
|
||||
return -ERANGE;
|
||||
}
|
||||
range->lob = lob;
|
||||
range->upb = lob + size - 1;
|
||||
range_invariant(range);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize @range to span the interval [@lob,@lob + @size - 1].
|
||||
* @size may be 0. Range must not overflow.
|
||||
*/
|
||||
static inline void range_init_nofail(Range *range, uint64_t lob, uint64_t size)
|
||||
{
|
||||
range->lob = lob;
|
||||
range->upb = lob + size - 1;
|
||||
range_invariant(range);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the size of @range.
|
||||
*/
|
||||
static inline uint64_t range_size(const Range *range)
|
||||
{
|
||||
return range->upb - range->lob + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if @range1 overlaps with @range2. If one of the ranges is empty,
|
||||
* the result is always "false".
|
||||
*/
|
||||
static inline bool range_overlaps_range(const Range *range1,
|
||||
const Range *range2)
|
||||
{
|
||||
if (range_is_empty(range1) || range_is_empty(range2)) {
|
||||
return false;
|
||||
}
|
||||
return !(range2->upb < range1->lob || range1->upb < range2->lob);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if @range1 contains @range2. If one of the ranges is empty,
|
||||
* the result is always "false".
|
||||
*/
|
||||
static inline bool range_contains_range(const Range *range1,
|
||||
const Range *range2)
|
||||
{
|
||||
if (range_is_empty(range1) || range_is_empty(range2)) {
|
||||
return false;
|
||||
}
|
||||
return range1->lob <= range2->lob && range1->upb >= range2->upb;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extend @range to the smallest interval that includes @extend_by, too.
|
||||
*/
|
||||
static inline void range_extend(Range *range, Range *extend_by)
|
||||
{
|
||||
if (range_is_empty(extend_by)) {
|
||||
return;
|
||||
}
|
||||
if (range_is_empty(range)) {
|
||||
*range = *extend_by;
|
||||
return;
|
||||
}
|
||||
if (range->lob > extend_by->lob) {
|
||||
range->lob = extend_by->lob;
|
||||
}
|
||||
if (range->upb < extend_by->upb) {
|
||||
range->upb = extend_by->upb;
|
||||
}
|
||||
range_invariant(range);
|
||||
}
|
||||
|
||||
/* Get last byte of a range from offset + length.
|
||||
* Undefined for ranges that wrap around 0. */
|
||||
static inline uint64_t range_get_last(uint64_t offset, uint64_t len)
|
||||
{
|
||||
return offset + len - 1;
|
||||
}
|
||||
|
||||
/* Check whether a given range covers a given byte. */
|
||||
static inline int range_covers_byte(uint64_t offset, uint64_t len,
|
||||
uint64_t byte)
|
||||
{
|
||||
return offset <= byte && byte <= range_get_last(offset, len);
|
||||
}
|
||||
|
||||
/* Check whether 2 given ranges overlap.
|
||||
* Undefined if ranges that wrap around 0. */
|
||||
static inline bool ranges_overlap(uint64_t first1, uint64_t len1,
|
||||
uint64_t first2, uint64_t len2)
|
||||
{
|
||||
uint64_t last1 = range_get_last(first1, len1);
|
||||
uint64_t last2 = range_get_last(first2, len2);
|
||||
|
||||
return !(last2 < first1 || last1 < first2);
|
||||
}
|
||||
|
||||
/* Get highest non-zero bit position of a range */
|
||||
static inline int range_get_last_bit(Range *range)
|
||||
{
|
||||
if (range_is_empty(range)) {
|
||||
return -1;
|
||||
}
|
||||
return 63 - clz64(range->upb);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return -1 if @a < @b, 1 @a > @b, and 0 if they touch or overlap.
|
||||
* Both @a and @b must not be empty.
|
||||
*/
|
||||
int range_compare(Range *a, Range *b);
|
||||
|
||||
GList *range_list_insert(GList *list, Range *data);
|
||||
|
||||
/*
|
||||
* Inverse an array of sorted ranges over the [low, high] span, ie.
|
||||
* original ranges becomes holes in the newly allocated inv_ranges
|
||||
*/
|
||||
void range_inverse_array(GList *in_ranges,
|
||||
GList **out_ranges,
|
||||
uint64_t low, uint64_t high);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Ratelimiting calculations
|
||||
*
|
||||
* Copyright IBM, Corp. 2011
|
||||
*
|
||||
* Authors:
|
||||
* Stefan Hajnoczi <[email protected]>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QEMU_RATELIMIT_H
|
||||
#define QEMU_RATELIMIT_H
|
||||
|
||||
#include "qemu/lockable.h"
|
||||
#include "qemu/timer.h"
|
||||
|
||||
typedef struct {
|
||||
QemuMutex lock;
|
||||
int64_t slice_start_time;
|
||||
int64_t slice_end_time;
|
||||
uint64_t slice_quota;
|
||||
uint64_t slice_ns;
|
||||
uint64_t dispatched;
|
||||
} RateLimit;
|
||||
|
||||
/** Calculate and return delay for next request in ns
|
||||
*
|
||||
* Record that we sent @n data units (where @n matches the scale chosen
|
||||
* during ratelimit_set_speed). If we may send more data units
|
||||
* in the current time slice, return 0 (i.e. no delay). Otherwise
|
||||
* return the amount of time (in ns) until the start of the next time
|
||||
* slice that will permit sending the next chunk of data.
|
||||
*
|
||||
* Recording sent data units even after exceeding the quota is
|
||||
* permitted; the time slice will be extended accordingly.
|
||||
*/
|
||||
static inline int64_t ratelimit_calculate_delay(RateLimit *limit, uint64_t n)
|
||||
{
|
||||
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
|
||||
double delay_slices;
|
||||
|
||||
QEMU_LOCK_GUARD(&limit->lock);
|
||||
if (!limit->slice_quota) {
|
||||
/* Throttling disabled. */
|
||||
return 0;
|
||||
}
|
||||
assert(limit->slice_ns);
|
||||
|
||||
if (limit->slice_end_time < now) {
|
||||
/* Previous, possibly extended, time slice finished; reset the
|
||||
* accounting. */
|
||||
limit->slice_start_time = now;
|
||||
limit->slice_end_time = now + limit->slice_ns;
|
||||
limit->dispatched = 0;
|
||||
}
|
||||
|
||||
limit->dispatched += n;
|
||||
if (limit->dispatched < limit->slice_quota) {
|
||||
/* We may send further data within the current time slice, no
|
||||
* need to delay the next request. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Quota exceeded. Wait based on the excess amount and then start a new
|
||||
* slice. */
|
||||
delay_slices = (double)limit->dispatched / limit->slice_quota;
|
||||
limit->slice_end_time = limit->slice_start_time +
|
||||
(uint64_t)(delay_slices * limit->slice_ns);
|
||||
return limit->slice_end_time - now;
|
||||
}
|
||||
|
||||
static inline void ratelimit_init(RateLimit *limit)
|
||||
{
|
||||
qemu_mutex_init(&limit->lock);
|
||||
}
|
||||
|
||||
static inline void ratelimit_destroy(RateLimit *limit)
|
||||
{
|
||||
qemu_mutex_destroy(&limit->lock);
|
||||
}
|
||||
|
||||
static inline void ratelimit_set_speed(RateLimit *limit, uint64_t speed,
|
||||
uint64_t slice_ns)
|
||||
{
|
||||
QEMU_LOCK_GUARD(&limit->lock);
|
||||
limit->slice_ns = slice_ns;
|
||||
if (speed == 0) {
|
||||
limit->slice_quota = 0;
|
||||
} else {
|
||||
limit->slice_quota = MAX(((double)speed * slice_ns) / 1000000000ULL, 1);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,198 @@
|
||||
#ifndef QEMU_RCU_H
|
||||
#define QEMU_RCU_H
|
||||
|
||||
/*
|
||||
* urcu-mb.h
|
||||
*
|
||||
* Userspace RCU header with explicit memory barrier.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* IBM's contributions to this file may be relicensed under LGPLv2 or later.
|
||||
*/
|
||||
|
||||
|
||||
#include "qemu/thread.h"
|
||||
#include "qemu/queue.h"
|
||||
#include "qemu/atomic.h"
|
||||
#include "qemu/notify.h"
|
||||
#include "qemu/sys_membarrier.h"
|
||||
#include "qemu/coroutine-tls.h"
|
||||
|
||||
/*
|
||||
* Important !
|
||||
*
|
||||
* Each thread containing read-side critical sections must be registered
|
||||
* with rcu_register_thread() before calling rcu_read_lock().
|
||||
* rcu_unregister_thread() should be called before the thread exits.
|
||||
*/
|
||||
|
||||
#ifdef DEBUG_RCU
|
||||
#define rcu_assert(args...) assert(args)
|
||||
#else
|
||||
#define rcu_assert(args...)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Global quiescent period counter with low-order bits unused.
|
||||
* Using a int rather than a char to eliminate false register dependencies
|
||||
* causing stalls on some architectures.
|
||||
*/
|
||||
extern unsigned long rcu_gp_ctr;
|
||||
|
||||
extern QemuEvent rcu_gp_event;
|
||||
|
||||
struct rcu_reader_data {
|
||||
/* Data used by both reader and synchronize_rcu() */
|
||||
unsigned long ctr;
|
||||
bool waiting;
|
||||
|
||||
/* Data used by reader only */
|
||||
unsigned depth;
|
||||
|
||||
/* Data used for registry, protected by rcu_registry_lock */
|
||||
QLIST_ENTRY(rcu_reader_data) node;
|
||||
|
||||
/*
|
||||
* NotifierList used to force an RCU grace period. Accessed under
|
||||
* rcu_registry_lock. Note that the notifier is called _outside_
|
||||
* the thread!
|
||||
*/
|
||||
NotifierList force_rcu;
|
||||
};
|
||||
|
||||
QEMU_DECLARE_CO_TLS(struct rcu_reader_data, rcu_reader)
|
||||
|
||||
static inline void rcu_read_lock(void)
|
||||
{
|
||||
struct rcu_reader_data *p_rcu_reader = get_ptr_rcu_reader();
|
||||
unsigned ctr;
|
||||
|
||||
if (p_rcu_reader->depth++ > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ctr = qatomic_read(&rcu_gp_ctr);
|
||||
qatomic_set(&p_rcu_reader->ctr, ctr);
|
||||
|
||||
/*
|
||||
* Read rcu_gp_ptr and write p_rcu_reader->ctr before reading
|
||||
* RCU-protected pointers.
|
||||
*/
|
||||
smp_mb_placeholder();
|
||||
}
|
||||
|
||||
static inline void rcu_read_unlock(void)
|
||||
{
|
||||
struct rcu_reader_data *p_rcu_reader = get_ptr_rcu_reader();
|
||||
|
||||
assert(p_rcu_reader->depth != 0);
|
||||
if (--p_rcu_reader->depth > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ensure that the critical section is seen to precede the
|
||||
* store to p_rcu_reader->ctr. Together with the following
|
||||
* smp_mb_placeholder(), this ensures writes to p_rcu_reader->ctr
|
||||
* are sequentially consistent.
|
||||
*/
|
||||
qatomic_store_release(&p_rcu_reader->ctr, 0);
|
||||
|
||||
/* Write p_rcu_reader->ctr before reading p_rcu_reader->waiting. */
|
||||
smp_mb_placeholder();
|
||||
if (unlikely(qatomic_read(&p_rcu_reader->waiting))) {
|
||||
qatomic_set(&p_rcu_reader->waiting, false);
|
||||
qemu_event_set(&rcu_gp_event);
|
||||
}
|
||||
}
|
||||
|
||||
void synchronize_rcu(void);
|
||||
|
||||
/*
|
||||
* Reader thread registration.
|
||||
*/
|
||||
void rcu_register_thread(void);
|
||||
void rcu_unregister_thread(void);
|
||||
|
||||
/*
|
||||
* Support for fork(). fork() support is enabled at startup.
|
||||
*/
|
||||
void rcu_enable_atfork(void);
|
||||
void rcu_disable_atfork(void);
|
||||
|
||||
struct rcu_head;
|
||||
typedef void RCUCBFunc(struct rcu_head *head);
|
||||
|
||||
struct rcu_head {
|
||||
struct rcu_head *next;
|
||||
RCUCBFunc *func;
|
||||
};
|
||||
|
||||
void call_rcu1(struct rcu_head *head, RCUCBFunc *func);
|
||||
void drain_call_rcu(void);
|
||||
|
||||
/* The operands of the minus operator must have the same type,
|
||||
* which must be the one that we specify in the cast.
|
||||
*/
|
||||
#define call_rcu(head, func, field) \
|
||||
call_rcu1(({ \
|
||||
char __attribute__((unused)) \
|
||||
offset_must_be_zero[-offsetof(typeof(*(head)), field)], \
|
||||
func_type_invalid = (func) - (void (*)(typeof(head)))(func); \
|
||||
&(head)->field; \
|
||||
}), \
|
||||
(RCUCBFunc *)(func))
|
||||
|
||||
#define g_free_rcu(obj, field) \
|
||||
call_rcu1(({ \
|
||||
char __attribute__((unused)) \
|
||||
offset_must_be_zero[-offsetof(typeof(*(obj)), field)]; \
|
||||
&(obj)->field; \
|
||||
}), \
|
||||
(RCUCBFunc *)g_free);
|
||||
|
||||
typedef void RCUReadAuto;
|
||||
static inline RCUReadAuto *rcu_read_auto_lock(void)
|
||||
{
|
||||
rcu_read_lock();
|
||||
/* Anything non-NULL causes the cleanup function to be called */
|
||||
return (void *)(uintptr_t)0x1;
|
||||
}
|
||||
|
||||
static inline void rcu_read_auto_unlock(RCUReadAuto *r)
|
||||
{
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(RCUReadAuto, rcu_read_auto_unlock)
|
||||
|
||||
#define WITH_RCU_READ_LOCK_GUARD() \
|
||||
WITH_RCU_READ_LOCK_GUARD_(glue(_rcu_read_auto, __COUNTER__))
|
||||
|
||||
#define WITH_RCU_READ_LOCK_GUARD_(var) \
|
||||
for (g_autoptr(RCUReadAuto) var = rcu_read_auto_lock(); \
|
||||
(var); rcu_read_auto_unlock(var), (var) = NULL)
|
||||
|
||||
#define RCU_READ_LOCK_GUARD() \
|
||||
g_autoptr(RCUReadAuto) _rcu_read_auto __attribute__((unused)) = rcu_read_auto_lock()
|
||||
|
||||
/*
|
||||
* Force-RCU notifiers tell readers that they should exit their
|
||||
* read-side critical section.
|
||||
*/
|
||||
void rcu_add_force_rcu_notifier(Notifier *n);
|
||||
void rcu_remove_force_rcu_notifier(Notifier *n);
|
||||
|
||||
#endif /* QEMU_RCU_H */
|
||||
@@ -0,0 +1,309 @@
|
||||
#ifndef QEMU_RCU_QUEUE_H
|
||||
#define QEMU_RCU_QUEUE_H
|
||||
|
||||
/*
|
||||
* rcu_queue.h
|
||||
*
|
||||
* RCU-friendly versions of the queue.h primitives.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Copyright (c) 2013 Mike D. Day, IBM Corporation.
|
||||
*
|
||||
* IBM's contributions to this file may be relicensed under LGPLv2 or later.
|
||||
*/
|
||||
|
||||
#include "qemu/queue.h"
|
||||
#include "qemu/atomic.h"
|
||||
|
||||
/*
|
||||
* List access methods.
|
||||
*/
|
||||
#define QLIST_EMPTY_RCU(head) (qatomic_read(&(head)->lh_first) == NULL)
|
||||
#define QLIST_FIRST_RCU(head) (qatomic_rcu_read(&(head)->lh_first))
|
||||
#define QLIST_NEXT_RCU(elm, field) (qatomic_rcu_read(&(elm)->field.le_next))
|
||||
|
||||
/*
|
||||
* List functions.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* The difference between qatomic_read/set and qatomic_rcu_read/set
|
||||
* is in the including of a read/write memory barrier to the volatile
|
||||
* access. atomic_rcu_* macros include the memory barrier, the
|
||||
* plain atomic macros do not. Therefore, it should be correct to
|
||||
* issue a series of reads or writes to the same element using only
|
||||
* the atomic_* macro, until the last read or write, which should be
|
||||
* atomic_rcu_* to introduce a read or write memory barrier as
|
||||
* appropriate.
|
||||
*/
|
||||
|
||||
/* Upon publication of the listelm->next value, list readers
|
||||
* will see the new node when following next pointers from
|
||||
* antecedent nodes, but may not see the new node when following
|
||||
* prev pointers from subsequent nodes until after the RCU grace
|
||||
* period expires.
|
||||
* see linux/include/rculist.h __list_add_rcu(new, prev, next)
|
||||
*/
|
||||
#define QLIST_INSERT_AFTER_RCU(listelm, elm, field) do { \
|
||||
(elm)->field.le_next = (listelm)->field.le_next; \
|
||||
(elm)->field.le_prev = &(listelm)->field.le_next; \
|
||||
qatomic_rcu_set(&(listelm)->field.le_next, (elm)); \
|
||||
if ((elm)->field.le_next != NULL) { \
|
||||
(elm)->field.le_next->field.le_prev = \
|
||||
&(elm)->field.le_next; \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/* Upon publication of the listelm->prev->next value, list
|
||||
* readers will see the new element when following prev pointers
|
||||
* from subsequent elements, but may not see the new element
|
||||
* when following next pointers from antecedent elements
|
||||
* until after the RCU grace period expires.
|
||||
*/
|
||||
#define QLIST_INSERT_BEFORE_RCU(listelm, elm, field) do { \
|
||||
(elm)->field.le_prev = (listelm)->field.le_prev; \
|
||||
(elm)->field.le_next = (listelm); \
|
||||
qatomic_rcu_set((listelm)->field.le_prev, (elm)); \
|
||||
(listelm)->field.le_prev = &(elm)->field.le_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/* Upon publication of the head->first value, list readers
|
||||
* will see the new element when following the head, but may
|
||||
* not see the new element when following prev pointers from
|
||||
* subsequent elements until after the RCU grace period has
|
||||
* expired.
|
||||
*/
|
||||
#define QLIST_INSERT_HEAD_RCU(head, elm, field) do { \
|
||||
(elm)->field.le_prev = &(head)->lh_first; \
|
||||
(elm)->field.le_next = (head)->lh_first; \
|
||||
qatomic_rcu_set((&(head)->lh_first), (elm)); \
|
||||
if ((elm)->field.le_next != NULL) { \
|
||||
(elm)->field.le_next->field.le_prev = \
|
||||
&(elm)->field.le_next; \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
|
||||
/* prior to publication of the elm->prev->next value, some list
|
||||
* readers may still see the removed element when following
|
||||
* the antecedent's next pointer.
|
||||
*/
|
||||
#define QLIST_REMOVE_RCU(elm, field) do { \
|
||||
if ((elm)->field.le_next != NULL) { \
|
||||
(elm)->field.le_next->field.le_prev = \
|
||||
(elm)->field.le_prev; \
|
||||
} \
|
||||
qatomic_set((elm)->field.le_prev, (elm)->field.le_next); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/* List traversal must occur within an RCU critical section. */
|
||||
#define QLIST_FOREACH_RCU(var, head, field) \
|
||||
for ((var) = qatomic_rcu_read(&(head)->lh_first); \
|
||||
(var); \
|
||||
(var) = qatomic_rcu_read(&(var)->field.le_next))
|
||||
|
||||
/* List traversal must occur within an RCU critical section. */
|
||||
#define QLIST_FOREACH_SAFE_RCU(var, head, field, next_var) \
|
||||
for ((var) = (qatomic_rcu_read(&(head)->lh_first)); \
|
||||
(var) && \
|
||||
((next_var) = qatomic_rcu_read(&(var)->field.le_next), 1); \
|
||||
(var) = (next_var))
|
||||
|
||||
/*
|
||||
* RCU simple queue
|
||||
*/
|
||||
|
||||
/* Simple queue access methods */
|
||||
#define QSIMPLEQ_EMPTY_RCU(head) \
|
||||
(qatomic_read(&(head)->sqh_first) == NULL)
|
||||
#define QSIMPLEQ_FIRST_RCU(head) qatomic_rcu_read(&(head)->sqh_first)
|
||||
#define QSIMPLEQ_NEXT_RCU(elm, field) qatomic_rcu_read(&(elm)->field.sqe_next)
|
||||
|
||||
/* Simple queue functions */
|
||||
#define QSIMPLEQ_INSERT_HEAD_RCU(head, elm, field) do { \
|
||||
(elm)->field.sqe_next = (head)->sqh_first; \
|
||||
if ((elm)->field.sqe_next == NULL) { \
|
||||
(head)->sqh_last = &(elm)->field.sqe_next; \
|
||||
} \
|
||||
qatomic_rcu_set(&(head)->sqh_first, (elm)); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSIMPLEQ_INSERT_TAIL_RCU(head, elm, field) do { \
|
||||
(elm)->field.sqe_next = NULL; \
|
||||
qatomic_rcu_set((head)->sqh_last, (elm)); \
|
||||
(head)->sqh_last = &(elm)->field.sqe_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSIMPLEQ_INSERT_AFTER_RCU(head, listelm, elm, field) do { \
|
||||
(elm)->field.sqe_next = (listelm)->field.sqe_next; \
|
||||
if ((elm)->field.sqe_next == NULL) { \
|
||||
(head)->sqh_last = &(elm)->field.sqe_next; \
|
||||
} \
|
||||
qatomic_rcu_set(&(listelm)->field.sqe_next, (elm)); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSIMPLEQ_REMOVE_HEAD_RCU(head, field) do { \
|
||||
qatomic_set(&(head)->sqh_first, (head)->sqh_first->field.sqe_next);\
|
||||
if ((head)->sqh_first == NULL) { \
|
||||
(head)->sqh_last = &(head)->sqh_first; \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSIMPLEQ_REMOVE_RCU(head, elm, type, field) do { \
|
||||
if ((head)->sqh_first == (elm)) { \
|
||||
QSIMPLEQ_REMOVE_HEAD_RCU((head), field); \
|
||||
} else { \
|
||||
struct type *curr = (head)->sqh_first; \
|
||||
while (curr->field.sqe_next != (elm)) { \
|
||||
curr = curr->field.sqe_next; \
|
||||
} \
|
||||
qatomic_set(&curr->field.sqe_next, \
|
||||
curr->field.sqe_next->field.sqe_next); \
|
||||
if (curr->field.sqe_next == NULL) { \
|
||||
(head)->sqh_last = &(curr)->field.sqe_next; \
|
||||
} \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSIMPLEQ_FOREACH_RCU(var, head, field) \
|
||||
for ((var) = qatomic_rcu_read(&(head)->sqh_first); \
|
||||
(var); \
|
||||
(var) = qatomic_rcu_read(&(var)->field.sqe_next))
|
||||
|
||||
#define QSIMPLEQ_FOREACH_SAFE_RCU(var, head, field, next) \
|
||||
for ((var) = qatomic_rcu_read(&(head)->sqh_first); \
|
||||
(var) && ((next) = qatomic_rcu_read(&(var)->field.sqe_next), 1);\
|
||||
(var) = (next))
|
||||
|
||||
/*
|
||||
* RCU tail queue
|
||||
*/
|
||||
|
||||
/* Tail queue access methods */
|
||||
#define QTAILQ_EMPTY_RCU(head) (qatomic_read(&(head)->tqh_first) == NULL)
|
||||
#define QTAILQ_FIRST_RCU(head) qatomic_rcu_read(&(head)->tqh_first)
|
||||
#define QTAILQ_NEXT_RCU(elm, field) qatomic_rcu_read(&(elm)->field.tqe_next)
|
||||
|
||||
/* Tail queue functions */
|
||||
#define QTAILQ_INSERT_HEAD_RCU(head, elm, field) do { \
|
||||
(elm)->field.tqe_next = (head)->tqh_first; \
|
||||
if ((elm)->field.tqe_next != NULL) { \
|
||||
(head)->tqh_first->field.tqe_circ.tql_prev = \
|
||||
&(elm)->field.tqe_circ; \
|
||||
} else { \
|
||||
(head)->tqh_circ.tql_prev = &(elm)->field.tqe_circ; \
|
||||
} \
|
||||
qatomic_rcu_set(&(head)->tqh_first, (elm)); \
|
||||
(elm)->field.tqe_circ.tql_prev = &(head)->tqh_circ; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QTAILQ_INSERT_TAIL_RCU(head, elm, field) do { \
|
||||
(elm)->field.tqe_next = NULL; \
|
||||
(elm)->field.tqe_circ.tql_prev = (head)->tqh_circ.tql_prev; \
|
||||
qatomic_rcu_set(&(head)->tqh_circ.tql_prev->tql_next, (elm)); \
|
||||
(head)->tqh_circ.tql_prev = &(elm)->field.tqe_circ; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QTAILQ_INSERT_AFTER_RCU(head, listelm, elm, field) do { \
|
||||
(elm)->field.tqe_next = (listelm)->field.tqe_next; \
|
||||
if ((elm)->field.tqe_next != NULL) { \
|
||||
(elm)->field.tqe_next->field.tqe_circ.tql_prev = \
|
||||
&(elm)->field.tqe_circ; \
|
||||
} else { \
|
||||
(head)->tqh_circ.tql_prev = &(elm)->field.tqe_circ; \
|
||||
} \
|
||||
qatomic_rcu_set(&(listelm)->field.tqe_next, (elm)); \
|
||||
(elm)->field.tqe_circ.tql_prev = &(listelm)->field.tqe_circ; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QTAILQ_INSERT_BEFORE_RCU(listelm, elm, field) do { \
|
||||
(elm)->field.tqe_circ.tql_prev = (listelm)->field.tqe_circ.tql_prev; \
|
||||
(elm)->field.tqe_next = (listelm); \
|
||||
qatomic_rcu_set(&(listelm)->field.tqe_circ.tql_prev->tql_next, (elm));\
|
||||
(listelm)->field.tqe_circ.tql_prev = &(elm)->field.tqe_circ; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QTAILQ_REMOVE_RCU(head, elm, field) do { \
|
||||
if (((elm)->field.tqe_next) != NULL) { \
|
||||
(elm)->field.tqe_next->field.tqe_circ.tql_prev = \
|
||||
(elm)->field.tqe_circ.tql_prev; \
|
||||
} else { \
|
||||
(head)->tqh_circ.tql_prev = (elm)->field.tqe_circ.tql_prev; \
|
||||
} \
|
||||
qatomic_set(&(elm)->field.tqe_circ.tql_prev->tql_next, \
|
||||
(elm)->field.tqe_next); \
|
||||
(elm)->field.tqe_circ.tql_prev = NULL; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QTAILQ_FOREACH_RCU(var, head, field) \
|
||||
for ((var) = qatomic_rcu_read(&(head)->tqh_first); \
|
||||
(var); \
|
||||
(var) = qatomic_rcu_read(&(var)->field.tqe_next))
|
||||
|
||||
#define QTAILQ_FOREACH_SAFE_RCU(var, head, field, next) \
|
||||
for ((var) = qatomic_rcu_read(&(head)->tqh_first); \
|
||||
(var) && ((next) = qatomic_rcu_read(&(var)->field.tqe_next), 1);\
|
||||
(var) = (next))
|
||||
|
||||
/*
|
||||
* RCU singly-linked list
|
||||
*/
|
||||
|
||||
/* Singly-linked list access methods */
|
||||
#define QSLIST_EMPTY_RCU(head) (qatomic_read(&(head)->slh_first) == NULL)
|
||||
#define QSLIST_FIRST_RCU(head) qatomic_rcu_read(&(head)->slh_first)
|
||||
#define QSLIST_NEXT_RCU(elm, field) qatomic_rcu_read(&(elm)->field.sle_next)
|
||||
|
||||
/* Singly-linked list functions */
|
||||
#define QSLIST_INSERT_HEAD_RCU(head, elm, field) do { \
|
||||
(elm)->field.sle_next = (head)->slh_first; \
|
||||
qatomic_rcu_set(&(head)->slh_first, (elm)); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSLIST_INSERT_AFTER_RCU(head, listelm, elm, field) do { \
|
||||
(elm)->field.sle_next = (listelm)->field.sle_next; \
|
||||
qatomic_rcu_set(&(listelm)->field.sle_next, (elm)); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSLIST_REMOVE_HEAD_RCU(head, field) do { \
|
||||
qatomic_set(&(head)->slh_first, (head)->slh_first->field.sle_next);\
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSLIST_REMOVE_RCU(head, elm, type, field) do { \
|
||||
if ((head)->slh_first == (elm)) { \
|
||||
QSLIST_REMOVE_HEAD_RCU((head), field); \
|
||||
} else { \
|
||||
struct type *curr = (head)->slh_first; \
|
||||
while (curr->field.sle_next != (elm)) { \
|
||||
curr = curr->field.sle_next; \
|
||||
} \
|
||||
qatomic_set(&curr->field.sle_next, \
|
||||
curr->field.sle_next->field.sle_next); \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSLIST_FOREACH_RCU(var, head, field) \
|
||||
for ((var) = qatomic_rcu_read(&(head)->slh_first); \
|
||||
(var); \
|
||||
(var) = qatomic_rcu_read(&(var)->field.sle_next))
|
||||
|
||||
#define QSLIST_FOREACH_SAFE_RCU(var, head, field, next) \
|
||||
for ((var) = qatomic_rcu_read(&(head)->slh_first); \
|
||||
(var) && ((next) = qatomic_rcu_read(&(var)->field.sle_next), 1); \
|
||||
(var) = (next))
|
||||
|
||||
#endif /* QEMU_RCU_QUEUE_H */
|
||||
@@ -0,0 +1,66 @@
|
||||
#ifndef READLINE_H
|
||||
#define READLINE_H
|
||||
|
||||
#define READLINE_CMD_BUF_SIZE 4095
|
||||
#define READLINE_MAX_CMDS 64
|
||||
#define READLINE_MAX_COMPLETIONS 256
|
||||
|
||||
typedef void G_GNUC_PRINTF(2, 3) ReadLinePrintfFunc(void *opaque,
|
||||
const char *fmt, ...);
|
||||
typedef void ReadLineFlushFunc(void *opaque);
|
||||
typedef void ReadLineFunc(void *opaque, const char *str,
|
||||
void *readline_opaque);
|
||||
typedef void ReadLineCompletionFunc(void *opaque,
|
||||
const char *cmdline);
|
||||
|
||||
typedef struct ReadLineState {
|
||||
char cmd_buf[READLINE_CMD_BUF_SIZE + 1];
|
||||
int cmd_buf_index;
|
||||
int cmd_buf_size;
|
||||
|
||||
char last_cmd_buf[READLINE_CMD_BUF_SIZE + 1];
|
||||
int last_cmd_buf_index;
|
||||
int last_cmd_buf_size;
|
||||
|
||||
int esc_state;
|
||||
int esc_param;
|
||||
|
||||
char *history[READLINE_MAX_CMDS];
|
||||
int hist_entry;
|
||||
|
||||
ReadLineCompletionFunc *completion_finder;
|
||||
char *completions[READLINE_MAX_COMPLETIONS];
|
||||
int nb_completions;
|
||||
int completion_index;
|
||||
|
||||
ReadLineFunc *readline_func;
|
||||
void *readline_opaque;
|
||||
int read_password;
|
||||
char prompt[256];
|
||||
|
||||
ReadLinePrintfFunc *printf_func;
|
||||
ReadLineFlushFunc *flush_func;
|
||||
void *opaque;
|
||||
} ReadLineState;
|
||||
|
||||
void readline_add_completion(ReadLineState *rs, const char *str);
|
||||
void readline_add_completion_of(ReadLineState *rs,
|
||||
const char *pfx, const char *str);
|
||||
void readline_set_completion_index(ReadLineState *rs, int completion_index);
|
||||
|
||||
const char *readline_get_history(ReadLineState *rs, unsigned int index);
|
||||
|
||||
void readline_handle_byte(ReadLineState *rs, int ch);
|
||||
|
||||
void readline_start(ReadLineState *rs, const char *prompt, int read_password,
|
||||
ReadLineFunc *readline_func, void *readline_opaque);
|
||||
void readline_restart(ReadLineState *rs);
|
||||
void readline_show_prompt(ReadLineState *rs);
|
||||
|
||||
ReadLineState *readline_init(ReadLinePrintfFunc *printf_func,
|
||||
ReadLineFlushFunc *flush_func,
|
||||
void *opaque,
|
||||
ReadLineCompletionFunc *completion_finder);
|
||||
void readline_free(ReadLineState *rs);
|
||||
|
||||
#endif /* READLINE_H */
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* QEMU ReservedRegion helpers
|
||||
*
|
||||
* Copyright (c) 2023 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_RESERVED_REGION_H
|
||||
#define QEMU_RESERVED_REGION_H
|
||||
|
||||
#include "system/memory.h"
|
||||
|
||||
/*
|
||||
* Insert a new region into a sorted list of reserved regions. In case
|
||||
* there is overlap with existing regions, the new added region has
|
||||
* higher priority and replaces the overlapped segment.
|
||||
*/
|
||||
GList *resv_region_list_insert(GList *list, ReservedRegion *reg);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* s390x PCI MMIO definitions
|
||||
*
|
||||
* Copyright 2025 IBM Corp.
|
||||
* Author(s): Farhan Ali <[email protected]>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#ifndef S390X_PCI_MMIO_H
|
||||
#define S390X_PCI_MMIO_H
|
||||
|
||||
#ifdef __s390x__
|
||||
uint8_t s390x_pci_mmio_read_8(const void *ioaddr);
|
||||
uint16_t s390x_pci_mmio_read_16(const void *ioaddr);
|
||||
uint32_t s390x_pci_mmio_read_32(const void *ioaddr);
|
||||
uint64_t s390x_pci_mmio_read_64(const void *ioaddr);
|
||||
|
||||
void s390x_pci_mmio_write_8(void *ioaddr, uint8_t val);
|
||||
void s390x_pci_mmio_write_16(void *ioaddr, uint16_t val);
|
||||
void s390x_pci_mmio_write_32(void *ioaddr, uint32_t val);
|
||||
void s390x_pci_mmio_write_64(void *ioaddr, uint64_t val);
|
||||
#endif /* __s390x__ */
|
||||
|
||||
#endif /* S390X_PCI_MMIO_H */
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Seqlock implementation for QEMU
|
||||
*
|
||||
* Copyright Red Hat, Inc. 2013
|
||||
*
|
||||
* Author:
|
||||
* Paolo Bonzini <[email protected]>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QEMU_SEQLOCK_H
|
||||
#define QEMU_SEQLOCK_H
|
||||
|
||||
#include "qemu/atomic.h"
|
||||
#include "qemu/thread.h"
|
||||
#include "qemu/lockable.h"
|
||||
|
||||
typedef struct QemuSeqLock QemuSeqLock;
|
||||
|
||||
struct QemuSeqLock {
|
||||
unsigned sequence;
|
||||
};
|
||||
|
||||
static inline void seqlock_init(QemuSeqLock *sl)
|
||||
{
|
||||
sl->sequence = 0;
|
||||
}
|
||||
|
||||
/* Lock out other writers and update the count. */
|
||||
static inline void seqlock_write_begin(QemuSeqLock *sl)
|
||||
{
|
||||
qatomic_set(&sl->sequence, sl->sequence + 1);
|
||||
|
||||
/* Write sequence before updating other fields. */
|
||||
smp_wmb();
|
||||
}
|
||||
|
||||
static inline void seqlock_write_end(QemuSeqLock *sl)
|
||||
{
|
||||
/* Write other fields before finalizing sequence. */
|
||||
smp_wmb();
|
||||
|
||||
qatomic_set(&sl->sequence, sl->sequence + 1);
|
||||
}
|
||||
|
||||
/* Lock out other writers and update the count. */
|
||||
static inline void seqlock_write_lock_impl(QemuSeqLock *sl, QemuLockable *lock)
|
||||
{
|
||||
qemu_lockable_lock(lock);
|
||||
seqlock_write_begin(sl);
|
||||
}
|
||||
#define seqlock_write_lock(sl, lock) \
|
||||
seqlock_write_lock_impl(sl, QEMU_MAKE_LOCKABLE(lock))
|
||||
|
||||
/* Update the count and release the lock. */
|
||||
static inline void seqlock_write_unlock_impl(QemuSeqLock *sl, QemuLockable *lock)
|
||||
{
|
||||
seqlock_write_end(sl);
|
||||
qemu_lockable_unlock(lock);
|
||||
}
|
||||
#define seqlock_write_unlock(sl, lock) \
|
||||
seqlock_write_unlock_impl(sl, QEMU_MAKE_LOCKABLE(lock))
|
||||
|
||||
|
||||
static inline unsigned seqlock_read_begin(const QemuSeqLock *sl)
|
||||
{
|
||||
/* Always fail if a write is in progress. */
|
||||
unsigned ret = qatomic_read(&sl->sequence);
|
||||
|
||||
/* Read sequence before reading other fields. */
|
||||
smp_rmb();
|
||||
return ret & ~1;
|
||||
}
|
||||
|
||||
static inline int seqlock_read_retry(const QemuSeqLock *sl, unsigned start)
|
||||
{
|
||||
/* Read other fields before reading final sequence. */
|
||||
smp_rmb();
|
||||
return unlikely(qatomic_read(&sl->sequence) != start);
|
||||
}
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user