Import QEMU upstream snapshot d2e570c

Upstream: https://gitlab.com/qemu-project/qemu.git

Upstream-Commit: d2e570cc0f97b936902a5b1b86b73c0f5998b475
This commit is contained in:
2026-08-31 02:15:30 +02:00
commit cf256aa081
11315 changed files with 3598369 additions and 0 deletions
+89
View File
@@ -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 */
+152
View File
@@ -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 */
+855
View File
@@ -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
+38
View File
@@ -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
+20
View File
@@ -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
+237
View File
@@ -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 */
+65
View File
@@ -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 */
+33
View File
@@ -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 */
+243
View File
@@ -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 */
+55
View File
@@ -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
+57
View File
@@ -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 */
+15
View File
@@ -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
+289
View File
@@ -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 */
+822
View File
@@ -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
+569
View File
@@ -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 */
+160
View File
@@ -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 */
+42
View File
@@ -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 */
+21
View File
@@ -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
+16
View File
@@ -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
+62
View File
@@ -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 */
+382
View File
@@ -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 */
+31
View File
@@ -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 */
+154
View File
@@ -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
+165
View File
@@ -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 */
+321
View File
@@ -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 */
+77
View File
@@ -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
+64
View File
@@ -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 */
+105
View File
@@ -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 */
+33
View File
@@ -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 */
+14
View File
@@ -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
+36
View File
@@ -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
+27
View File
@@ -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
+305
View File
@@ -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
+33
View File
@@ -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
+42
View File
@@ -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 */
+16
View File
@@ -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 */
+6
View File
@@ -0,0 +1,6 @@
#ifndef QEMU_DRM_H
#define QEMU_DRM_H
int qemu_drm_rendernode_open(const char *rendernode);
#endif
+12
View File
@@ -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 */
+83
View File
@@ -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
+46
View File
@@ -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
+57
View File
@@ -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 */
+190
View File
@@ -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 */
+230
View File
@@ -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 */
+127
View File
@@ -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 */
+79
View File
@@ -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 */
+68
View File
@@ -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 */
+353
View File
@@ -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
+13
View File
@@ -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
+33
View File
@@ -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
+136
View File
@@ -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
+929
View File
@@ -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
+17
View File
@@ -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
+15
View File
@@ -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
+495
View File
@@ -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 */
+99
View File
@@ -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 */
+278
View File
@@ -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
+164
View File
@@ -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
+59
View File
@@ -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 */
+736
View File
@@ -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
+15
View File
@@ -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 */
+184
View File
@@ -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
+130
View File
@@ -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
+50
View File
@@ -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
+140
View File
@@ -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
+95
View File
@@ -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
+452
View File
@@ -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
+10
View File
@@ -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
+61
View File
@@ -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
+47
View File
@@ -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 */
+66
View File
@@ -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
+192
View File
@@ -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
+14
View File
@@ -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
+80
View File
@@ -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
+6
View File
@@ -0,0 +1,6 @@
#ifndef NVDIMM_UTILS_H
#define NVDIMM_UTILS_H
GSList *nvdimm_get_device_list(void);
#endif
+152
View File
@@ -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
+54
View File
@@ -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
+878
View File
@@ -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
+7
View File
@@ -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
+30
View File
@@ -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 */
+30
View File
@@ -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 */
+35
View File
@@ -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 */
+327
View File
@@ -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 */
+35
View File
@@ -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 */
+25
View File
@@ -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 */
+62
View File
@@ -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 */
+61
View File
@@ -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 */
+23
View File
@@ -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
+8
View File
@@ -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 */
+224
View File
@@ -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 */
+27
View File
@@ -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 */
+200
View File
@@ -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 */
+576
View File
@@ -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 */
+247
View File
@@ -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
+97
View File
@@ -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
+198
View File
@@ -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 */
+309
View File
@@ -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 */
+66
View File
@@ -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 */
+32
View File
@@ -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
+24
View File
@@ -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 */
+85
View File
@@ -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