diff options
Diffstat (limited to 'include')
356 files changed, 8230 insertions, 2690 deletions
diff --git a/include/system/accel-ops.h b/include/accel/accel-cpu-ops.h index 4c99d25..0674764 100644 --- a/include/system/accel-ops.h +++ b/include/accel/accel-cpu-ops.h @@ -1,5 +1,5 @@ /* - * Accelerator OPS, used for cpus.c module + * Accelerator per-vCPU handlers * * Copyright 2021 SUSE LLC * @@ -7,9 +7,10 @@ * See the COPYING file in the top-level directory. */ -#ifndef ACCEL_OPS_H -#define ACCEL_OPS_H +#ifndef QEMU_ACCEL_CPU_OPS_H +#define QEMU_ACCEL_CPU_OPS_H +#include "qemu/accel.h" #include "exec/vaddr.h" #include "qom/object.h" @@ -31,7 +32,7 @@ struct AccelOpsClass { /*< public >*/ /* initialization function called when accel is chosen */ - void (*ops_init)(AccelOpsClass *ops); + void (*ops_init)(AccelClass *ac); bool (*cpus_are_resettable)(void); void (*cpu_reset_hold)(CPUState *cpu); @@ -40,14 +41,33 @@ struct AccelOpsClass { void (*kick_vcpu_thread)(CPUState *cpu); bool (*cpu_thread_is_idle)(CPUState *cpu); + /** + * synchronize_post_reset: + * synchronize_post_init: + * @cpu: The vCPU to synchronize. + * + * Request to synchronize QEMU vCPU registers to the hardware accelerator + * (QEMU is the reference). + */ void (*synchronize_post_reset)(CPUState *cpu); void (*synchronize_post_init)(CPUState *cpu); + /** + * synchronize_state: + * synchronize_pre_loadvm: + * @cpu: The vCPU to synchronize. + * + * Request to synchronize QEMU vCPU registers from the hardware accelerator + * (the hardware accelerator is the reference). + */ void (*synchronize_state)(CPUState *cpu); void (*synchronize_pre_loadvm)(CPUState *cpu); - void (*synchronize_pre_resume)(bool step_pending); + /* handle_interrupt is mandatory. */ void (*handle_interrupt)(CPUState *cpu, int mask); + /* get_vcpu_stats: Append statistics of this @cpu to @buf */ + void (*get_vcpu_stats)(CPUState *cpu, GString *buf); + /** * @get_virtual_clock: fetch virtual clock * @set_virtual_clock: set virtual clock @@ -70,4 +90,6 @@ struct AccelOpsClass { void (*remove_all_breakpoints)(CPUState *cpu); }; -#endif /* ACCEL_OPS_H */ +void generic_handle_interrupt(CPUState *cpu, int mask); + +#endif /* QEMU_ACCEL_CPU_OPS_H */ diff --git a/include/accel/accel-ops.h b/include/accel/accel-ops.h new file mode 100644 index 0000000..23a8c24 --- /dev/null +++ b/include/accel/accel-ops.h @@ -0,0 +1,51 @@ +/* + * Accelerator handlers + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef ACCEL_OPS_H +#define ACCEL_OPS_H + +#include "exec/hwaddr.h" +#include "qemu/accel.h" +#include "qom/object.h" + +struct AccelState { + Object parent_obj; +}; + +struct AccelClass { + ObjectClass parent_class; + + const char *name; + /* Cached by accel_init_ops_interfaces() when created */ + AccelOpsClass *ops; + + int (*init_machine)(AccelState *as, MachineState *ms); + bool (*cpu_common_realize)(CPUState *cpu, Error **errp); + void (*cpu_common_unrealize)(CPUState *cpu); + /* get_stats: Append statistics to @buf */ + void (*get_stats)(AccelState *as, GString *buf); + + /* system related hooks */ + void (*setup_post)(AccelState *as); + void (*pre_resume_vm)(AccelState *as, bool step_pending); + bool (*has_memory)(AccelState *accel, AddressSpace *as, + hwaddr start_addr, hwaddr size); + + /* gdbstub related hooks */ + int (*gdbstub_supported_sstep_flags)(AccelState *as); + + bool *allowed; + /* + * Array of global properties that would be applied when specific + * accelerator is chosen. It works like MachineClass.compat_props + * but it's for accelerators not machines. Accelerator-provided + * global properties may be overridden by machine-type + * compat_props or user-provided global properties. + */ + GPtrArray *compat_props; +}; + +#endif /* ACCEL_OPS_H */ diff --git a/include/accel/tcg/cpu-ldst-common.h b/include/accel/tcg/cpu-ldst-common.h index 8bf17c2..17a3250 100644 --- a/include/accel/tcg/cpu-ldst-common.h +++ b/include/accel/tcg/cpu-ldst-common.h @@ -100,9 +100,6 @@ GEN_ATOMIC_HELPER_ALL(umax_fetch) GEN_ATOMIC_HELPER_ALL(xchg) -#undef GEN_ATOMIC_HELPER_ALL -#undef GEN_ATOMIC_HELPER - Int128 cpu_atomic_cmpxchgo_le_mmu(CPUArchState *env, vaddr addr, Int128 cmpv, Int128 newv, MemOpIdx oi, uintptr_t retaddr); @@ -110,6 +107,16 @@ Int128 cpu_atomic_cmpxchgo_be_mmu(CPUArchState *env, vaddr addr, Int128 cmpv, Int128 newv, MemOpIdx oi, uintptr_t retaddr); +GEN_ATOMIC_HELPER(xchg, Int128, o_le) +GEN_ATOMIC_HELPER(xchg, Int128, o_be) +GEN_ATOMIC_HELPER(fetch_and, Int128, o_le) +GEN_ATOMIC_HELPER(fetch_and, Int128, o_be) +GEN_ATOMIC_HELPER(fetch_or, Int128, o_le) +GEN_ATOMIC_HELPER(fetch_or, Int128, o_be) + +#undef GEN_ATOMIC_HELPER_ALL +#undef GEN_ATOMIC_HELPER + uint8_t cpu_ldb_code_mmu(CPUArchState *env, vaddr addr, MemOpIdx oi, uintptr_t ra); uint16_t cpu_ldw_code_mmu(CPUArchState *env, vaddr addr, diff --git a/include/accel/tcg/cpu-ops.h b/include/accel/tcg/cpu-ops.h index cd22e5d..dd8ea30 100644 --- a/include/accel/tcg/cpu-ops.h +++ b/include/accel/tcg/cpu-ops.h @@ -223,6 +223,13 @@ struct TCGCPUOps { MMUAccessType access_type, int mmu_idx, bool probe, uintptr_t retaddr); /** + * @pointer_wrap: + * + * We have incremented @base to @result, resulting in a page change. + * For the current cpu state, adjust @result for possible overflow. + */ + vaddr (*pointer_wrap)(CPUState *cpu, int mmu_idx, vaddr result, vaddr base); + /** * @do_transaction_failed: Callback for handling failed memory transactions * (ie bus faults or external aborts; not MMU faults) */ @@ -315,6 +322,12 @@ void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len, */ int cpu_watchpoint_address_matches(CPUState *cpu, vaddr addr, vaddr len); +/* + * Common pointer_wrap implementations. + */ +vaddr cpu_pointer_wrap_notreached(CPUState *, int, vaddr, vaddr); +vaddr cpu_pointer_wrap_uint32(CPUState *, int, vaddr, vaddr); + #endif #endif /* TCG_CPU_OPS_H */ diff --git a/include/block/accounting.h b/include/block/accounting.h index a59e39f..b1cf417 100644 --- a/include/block/accounting.h +++ b/include/block/accounting.h @@ -101,8 +101,9 @@ typedef struct BlockAcctCookie { } BlockAcctCookie; void block_acct_init(BlockAcctStats *stats); -void block_acct_setup(BlockAcctStats *stats, enum OnOffAuto account_invalid, - enum OnOffAuto account_failed); +bool block_acct_setup(BlockAcctStats *stats, enum OnOffAuto account_invalid, + enum OnOffAuto account_failed, uint32_t *stats_intervals, + uint32_t num_stats_intervals, Error **errp); void block_acct_cleanup(BlockAcctStats *stats); void block_acct_add_interval(BlockAcctStats *stats, unsigned interval_length); BlockAcctTimedStats *block_acct_interval_next(BlockAcctStats *stats, diff --git a/include/block/aio.h b/include/block/aio.h index 99ff484..6049e6a 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -61,6 +61,27 @@ 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 { /* @@ -106,6 +127,78 @@ typedef struct { * 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; /* @@ -217,12 +310,14 @@ struct AioContext { struct LinuxAioState *linux_aio; #endif #ifdef CONFIG_LINUX_IO_URING - LuringState *linux_io_uring; - /* State for file descriptor monitoring using Linux io_uring */ struct io_uring fdmon_io_uring; AioHandlerSList submit_list; -#endif + 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. @@ -254,7 +349,13 @@ struct AioContext { /* 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; }; /** @@ -512,11 +613,6 @@ 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); -/* Setup the LuringState bound to this AioContext */ -LuringState *aio_setup_linux_io_uring(AioContext *ctx, Error **errp); - -/* Return the LuringState bound to this AioContext */ -LuringState *aio_get_linux_io_uring(AioContext *ctx); /** * aio_timer_new_with_attrs: * @ctx: the aio context @@ -650,6 +746,21 @@ void coroutine_fn aio_co_reschedule_self(AioContext *new_ctx); * 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); @@ -679,10 +790,13 @@ 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 */ -void aio_context_setup(AioContext *ctx); +bool aio_context_setup(AioContext *ctx, Error **errp); /** * aio_context_destroy: @@ -692,9 +806,6 @@ void aio_context_setup(AioContext *ctx); */ void aio_context_destroy(AioContext *ctx); -/* Used internally, do not call outside AioContext code */ -void aio_context_use_g_source(AioContext *ctx); - /** * aio_context_set_poll_params: * @ctx: the aio context @@ -724,4 +835,40 @@ void aio_context_set_aio_params(AioContext *ctx, int64_t max_batch); */ 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 diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h index 9be34b3..479ca28 100644 --- a/include/block/block-global-state.h +++ b/include/block/block-global-state.h @@ -65,7 +65,8 @@ int co_wrapper bdrv_create(BlockDriver *drv, const char *filename, QemuOpts *opts, Error **errp); int coroutine_fn GRAPH_UNLOCKED -bdrv_co_create_file(const char *filename, QemuOpts *opts, Error **errp); +bdrv_co_create_file(const char *filename, QemuOpts *opts, + bool allow_protocol_prefix, Error **errp); BlockDriverState *bdrv_new(void); int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top, @@ -74,13 +75,14 @@ int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top, int GRAPH_WRLOCK bdrv_replace_node(BlockDriverState *from, BlockDriverState *to, Error **errp); -int bdrv_replace_child_bs(BdrvChild *child, BlockDriverState *new_bs, - Error **errp); -BlockDriverState *bdrv_insert_node(BlockDriverState *bs, QDict *node_options, - int flags, Error **errp); +int GRAPH_UNLOCKED +bdrv_replace_child_bs(BdrvChild *child, BlockDriverState *new_bs, Error **errp); +BlockDriverState * GRAPH_UNLOCKED +bdrv_insert_node(BlockDriverState *bs, QDict *node_options, int flags, + Error **errp); int bdrv_drop_filter(BlockDriverState *bs, Error **errp); -BdrvChild * no_coroutine_fn +BdrvChild * no_coroutine_fn GRAPH_UNLOCKED bdrv_open_child(const char *filename, QDict *options, const char *bdref_key, BlockDriverState *parent, const BdrvChildClass *child_class, BdrvChildRole child_role, bool allow_none, Error **errp); @@ -90,9 +92,10 @@ bdrv_co_open_child(const char *filename, QDict *options, const char *bdref_key, BlockDriverState *parent, const BdrvChildClass *child_class, BdrvChildRole child_role, bool allow_none, Error **errp); -int bdrv_open_file_child(const char *filename, - QDict *options, const char *bdref_key, - BlockDriverState *parent, Error **errp); +int GRAPH_UNLOCKED +bdrv_open_file_child(const char *filename, QDict *options, + const char *bdref_key, BlockDriverState *parent, + Error **errp); BlockDriverState * no_coroutine_fn bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp); @@ -100,11 +103,9 @@ bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp); BlockDriverState * coroutine_fn no_co_wrapper bdrv_co_open_blockdev_ref(BlockdevRef *ref, Error **errp); -int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd, - Error **errp); int GRAPH_WRLOCK -bdrv_set_backing_hd_drained(BlockDriverState *bs, BlockDriverState *backing_hd, - Error **errp); +bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd, + Error **errp); int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options, const char *bdref_key, Error **errp); @@ -123,11 +124,12 @@ BlockDriverState *bdrv_new_open_driver_opts(BlockDriver *drv, Error **errp); BlockDriverState *bdrv_new_open_driver(BlockDriver *drv, const char *node_name, int flags, Error **errp); -BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue, - BlockDriverState *bs, QDict *options, - bool keep_old_opts); +BlockReopenQueue * GRAPH_UNLOCKED +bdrv_reopen_queue(BlockReopenQueue *bs_queue, BlockDriverState *bs, + QDict *options, bool keep_old_opts); void bdrv_reopen_queue_free(BlockReopenQueue *bs_queue); -int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp); +int GRAPH_UNLOCKED +bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp); int bdrv_reopen(BlockDriverState *bs, QDict *opts, bool keep_old_opts, Error **errp); int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only, @@ -143,9 +145,10 @@ int bdrv_commit(BlockDriverState *bs); int GRAPH_RDLOCK bdrv_make_empty(BdrvChild *c, Error **errp); void bdrv_register(BlockDriver *bdrv); -int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base, - const char *backing_file_str, - bool backing_mask_protocol); +int GRAPH_UNLOCKED +bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base, + const char *backing_file_str, + bool backing_mask_protocol); BlockDriverState * GRAPH_RDLOCK bdrv_find_overlay(BlockDriverState *active, BlockDriverState *bs); @@ -184,18 +187,18 @@ bdrv_activate(BlockDriverState *bs, Error **errp); int coroutine_fn no_co_wrapper_bdrv_rdlock bdrv_co_activate(BlockDriverState *bs, Error **errp); -int no_coroutine_fn +int no_coroutine_fn GRAPH_RDLOCK bdrv_inactivate(BlockDriverState *bs, Error **errp); void bdrv_activate_all(Error **errp); -int bdrv_inactivate_all(void); +int GRAPH_UNLOCKED bdrv_inactivate_all(void); int bdrv_flush_all(void); -void bdrv_close_all(void); -void bdrv_drain_all_begin(void); +void GRAPH_UNLOCKED bdrv_close_all(void); +void GRAPH_UNLOCKED bdrv_drain_all_begin(void); void bdrv_drain_all_begin_nopoll(void); void bdrv_drain_all_end(void); -void bdrv_drain_all(void); +void GRAPH_UNLOCKED bdrv_drain_all(void); void bdrv_aio_cancel(BlockAIOCB *acb); @@ -274,11 +277,16 @@ int bdrv_debug_remove_breakpoint(BlockDriverState *bs, const char *tag); int bdrv_debug_resume(BlockDriverState *bs, const char *tag); bool bdrv_debug_is_suspended(BlockDriverState *bs, const char *tag); -bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx, - GHashTable *visited, Transaction *tran, - Error **errp); -int bdrv_try_change_aio_context(BlockDriverState *bs, AioContext *ctx, - BdrvChild *ignore_child, Error **errp); +bool GRAPH_RDLOCK +bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx, + GHashTable *visited, Transaction *tran, + Error **errp); +int GRAPH_UNLOCKED +bdrv_try_change_aio_context(BlockDriverState *bs, AioContext *ctx, + BdrvChild *ignore_child, Error **errp); +int GRAPH_RDLOCK +bdrv_try_change_aio_context_locked(BlockDriverState *bs, AioContext *ctx, + BdrvChild *ignore_child, Error **errp); int GRAPH_RDLOCK bdrv_probe_blocksizes(BlockDriverState *bs, BlockSizes *bsz); int bdrv_probe_geometry(BlockDriverState *bs, HDGeometry *geo); diff --git a/include/block/block-io.h b/include/block/block-io.h index b99cc98..4cf83fb 100644 --- a/include/block/block-io.h +++ b/include/block/block-io.h @@ -431,7 +431,7 @@ bdrv_drain_poll(BlockDriverState *bs, BdrvChild *ignore_parent, * * This function can be recursive. */ -void bdrv_drained_begin(BlockDriverState *bs); +void GRAPH_UNLOCKED bdrv_drained_begin(BlockDriverState *bs); /** * bdrv_do_drained_begin_quiesce: diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h index 2982dd3..cb0143e 100644 --- a/include/block/block_int-common.h +++ b/include/block/block_int-common.h @@ -248,7 +248,7 @@ struct BlockDriver { int GRAPH_UNLOCKED_PTR (*bdrv_open)( BlockDriverState *bs, QDict *options, int flags, Error **errp); - void (*bdrv_close)(BlockDriverState *bs); + void GRAPH_UNLOCKED_PTR (*bdrv_close)(BlockDriverState *bs); int coroutine_fn GRAPH_UNLOCKED_PTR (*bdrv_co_create)( BlockdevCreateOptions *opts, Error **errp); @@ -396,9 +396,23 @@ struct BlockDriver { int GRAPH_RDLOCK_PTR (*bdrv_probe_geometry)( BlockDriverState *bs, HDGeometry *geo); + /** + * Hot add a BDS's child. Used in combination with bdrv_del_child, so the + * user can take a child offline when it is broken and take a new child + * online. + * + * All block nodes must be drained. + */ void GRAPH_WRLOCK_PTR (*bdrv_add_child)( BlockDriverState *parent, BlockDriverState *child, Error **errp); + /** + * Hot remove a BDS's child. Used in combination with bdrv_add_child, so the + * user can take a child offline when it is broken and take a new child + * online. + * + * All block nodes must be drained. + */ void GRAPH_WRLOCK_PTR (*bdrv_del_child)( BlockDriverState *parent, BdrvChild *child, Error **errp); @@ -494,7 +508,12 @@ struct BlockDriver { BlockDriverState *bs, BlockdevAmendOptions *opts, bool force, Error **errp); - /* aio */ + /* + * AIO + * The given completion callback will be run in the same AioContext as the + * one in which the AIO function was called. + */ + BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_preadv)(BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque); @@ -803,10 +822,10 @@ typedef struct BlockLimits { int64_t max_pdiscard; /* - * Optimal alignment for discard requests in bytes. A power of 2 - * is best but not mandatory. Must be a multiple of - * bl.request_alignment, and must be less than max_pdiscard if - * that is set. May be 0 if bl.request_alignment is good enough + * Optimal alignment for discard requests in bytes. Note that this doesn't + * have to be a power of two. Must be a multiple of bl.request_alignment, + * and must be less than max_pdiscard if that is set. May be 0 if + * bl.request_alignment is good enough. */ uint32_t pdiscard_alignment; @@ -817,11 +836,10 @@ typedef struct BlockLimits { int64_t max_pwrite_zeroes; /* - * Optimal alignment for write zeroes requests in bytes. A power - * of 2 is best but not mandatory. Must be a multiple of - * bl.request_alignment, and must be less than max_pwrite_zeroes - * if that is set. May be 0 if bl.request_alignment is good - * enough + * Optimal alignment for write zeroes requests in bytes. Note that this + * doesn't have to be a power of two. Must be a multiple of + * bl.request_alignment, and must be less than max_pwrite_zeroes if that is + * set. May be 0 if bl.request_alignment is good enough. */ uint32_t pwrite_zeroes_alignment; @@ -849,18 +867,23 @@ typedef struct BlockLimits { uint64_t max_hw_transfer; /* - * Maximal number of scatter/gather elements allowed by the hardware. + * Maximum number of scatter/gather elements allowed by the hardware. * Applies whenever transfers to the device bypass the kernel I/O * scheduler, for example with SG_IO. If larger than max_iov * or if zero, blk_get_max_hw_iov will fall back to max_iov. */ int max_hw_iov; - - /* memory alignment, in bytes so that no bounce buffer is needed */ + /* + * Minimal required memory alignment in bytes for zero-copy I/O to succeed. + * For unaligned requests, a bounce buffer will be used. + */ size_t min_mem_alignment; - /* memory alignment, in bytes, for bounce buffer */ + /* + * Optimal memory alignment in bytes. This is the alignment used for any + * buffer allocations QEMU performs internally. + */ size_t opt_mem_alignment; /* maximum number of iovec elements */ @@ -983,9 +1006,21 @@ struct BdrvChildClass { bool backing_mask_protocol, Error **errp); - bool (*change_aio_ctx)(BdrvChild *child, AioContext *ctx, - GHashTable *visited, Transaction *tran, - Error **errp); + /* + * Notifies the parent that the child is trying to change its AioContext. + * The parent may in turn change the AioContext of other nodes in the same + * transaction. Returns true if the change is possible and the transaction + * can be continued. Returns false and sets @errp if not and the transaction + * must be aborted. + * + * @visited will accumulate all visited BdrvChild objects. The caller is + * responsible for freeing the list afterwards. + * + * Must be called with the affected block nodes drained. + */ + bool GRAPH_RDLOCK_PTR (*change_aio_ctx)(BdrvChild *child, AioContext *ctx, + GHashTable *visited, + Transaction *tran, Error **errp); /* * I/O API functions. These functions are thread-safe. @@ -994,7 +1029,10 @@ struct BdrvChildClass { * the I/O API. */ - void (*resize)(BdrvChild *child); + /* + * Notifies the parent that the child was resized. + */ + void GRAPH_RDLOCK_PTR (*resize)(BdrvChild *child); /* * Returns a name that is supposedly more useful for human users than the @@ -1227,7 +1265,7 @@ struct BlockDriverState { /* do we need to tell the quest if we have a volatile write cache? */ int enable_write_cache; - /* Accessed with atomic ops. */ + /* Accessed only in the main thread. */ int quiesce_counter; unsigned int write_gen; /* Current data generation */ diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h index 4f94eb3..ed8b565 100644 --- a/include/block/block_int-io.h +++ b/include/block/block_int-io.h @@ -191,4 +191,10 @@ void bdrv_bsc_invalidate_range(BlockDriverState *bs, */ void bdrv_bsc_fill(BlockDriverState *bs, int64_t offset, int64_t bytes); +/* + * Notify all parents that the size of the child changed. + */ +void coroutine_fn GRAPH_RDLOCK +bdrv_co_parent_cb_resize(BlockDriverState *bs); + #endif /* BLOCK_INT_IO_H */ diff --git a/include/block/blockjob.h b/include/block/blockjob.h index 7061ab7..85284cb 100644 --- a/include/block/blockjob.h +++ b/include/block/blockjob.h @@ -137,6 +137,8 @@ BlockJob *block_job_get_locked(const char *id); * Add @bs to the list of BlockDriverState that are involved in * @job. This means that all operations will be blocked on @bs while * @job exists. + * + * All block nodes must be drained. */ int GRAPH_WRLOCK block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs, @@ -149,7 +151,7 @@ block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs, * Remove all BlockDriverStates from the list of nodes that are involved in the * job. This removes the blockers added with block_job_add_bdrv(). */ -void block_job_remove_all_bdrv(BlockJob *job); +void GRAPH_UNLOCKED block_job_remove_all_bdrv(BlockJob *job); /** * block_job_has_bdrv: diff --git a/include/block/graph-lock.h b/include/block/graph-lock.h index 2c26c72..95bf5ed 100644 --- a/include/block/graph-lock.h +++ b/include/block/graph-lock.h @@ -113,9 +113,20 @@ void no_coroutine_fn TSA_ACQUIRE(graph_lock) TSA_NO_TSA bdrv_graph_wrlock(void); /* + * bdrv_graph_wrlock_drained: + * Similar to bdrv_graph_wrlock, but will begin a drained section before + * locking. + */ +void no_coroutine_fn TSA_ACQUIRE(graph_lock) TSA_NO_TSA +bdrv_graph_wrlock_drained(void); + +/* * bdrv_graph_wrunlock: * Write finished, reset global has_writer to 0 and restart * all readers that are waiting. + * + * Also ends the drained section if bdrv_graph_wrlock_drained() was used to lock + * the graph. */ void no_coroutine_fn TSA_RELEASE(graph_lock) TSA_NO_TSA bdrv_graph_wrunlock(void); diff --git a/include/block/nbd.h b/include/block/nbd.h index 92987c7..ab40842 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -296,7 +296,7 @@ enum { NBD_CMD_BLOCK_STATUS = 7, }; -#define NBD_DEFAULT_PORT 10809 +#define NBD_DEFAULT_PORT 10809 /* Maximum size of a single READ/WRITE data buffer */ #define NBD_MAX_BUFFER_SIZE (32 * 1024 * 1024) diff --git a/include/block/nvme.h b/include/block/nvme.h index 358e516..8640dfa 100644 --- a/include/block/nvme.h +++ b/include/block/nvme.h @@ -1589,7 +1589,7 @@ enum NvmeIdNsMc { enum NvmeIdNsNsfeat { NVME_ID_NS_NSFEAT_THINP = 1 << 0, - NVME_ID_NS_NSFEAT_NSABPNS = 1 << 1, + NVME_ID_NS_NSFEAT_NSABP = 1 << 1, NVME_ID_NS_NSFEAT_DAE = 1 << 2, NVME_ID_NS_NSFEAT_UIDREUSE = 1 << 3, NVME_ID_NS_NSFEAT_OPTPERF_ALL = 3 << 4, @@ -1779,6 +1779,21 @@ enum NvmeDirectiveOperations { NVME_DIRECTIVE_RETURN_PARAMS = 0x1, }; +typedef enum SfscSecurityProtocol { + SFSC_SECURITY_PROT_INFO = 0x00, +} SfscSecurityProtocol; + +typedef enum NvmeSecurityProtocols { + NVME_SEC_PROT_DMTF_SPDM = 0xE8, +} NvmeSecurityProtocols; + +typedef enum SpdmOperationCodes { + SPDM_STORAGE_DISCOVERY = 0x1, /* Mandatory */ + SPDM_STORAGE_PENDING_INFO = 0x2, /* Optional */ + SPDM_STORAGE_MSG = 0x5, /* Mandatory */ + SPDM_STORAGE_SEC_MSG = 0x6, /* Optional */ +} SpdmOperationCodes; + typedef struct QEMU_PACKED NvmeFdpConfsHdr { uint16_t num_confs; uint8_t version; diff --git a/include/block/qapi.h b/include/block/qapi.h index 54c48de..be554e5 100644 --- a/include/block/qapi.h +++ b/include/block/qapi.h @@ -42,7 +42,7 @@ bdrv_query_image_info(BlockDriverState *bs, ImageInfo **p_info, bool flat, bool skip_implicit_filters, Error **errp); void GRAPH_RDLOCK bdrv_query_block_graph_info(BlockDriverState *bs, BlockGraphInfo **p_info, - Error **errp); + bool limits, Error **errp); void bdrv_snapshot_dump(QEMUSnapshotInfo *sn); void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec, diff --git a/include/block/raw-aio.h b/include/block/raw-aio.h index 6570244..30e5fc9 100644 --- a/include/block/raw-aio.h +++ b/include/block/raw-aio.h @@ -74,15 +74,10 @@ static inline bool laio_has_fua(void) #endif /* io_uring.c - Linux io_uring implementation */ #ifdef CONFIG_LINUX_IO_URING -LuringState *luring_init(Error **errp); -void luring_cleanup(LuringState *s); - /* luring_co_submit: submit I/O requests in the thread's current AioContext. */ int coroutine_fn luring_co_submit(BlockDriverState *bs, int fd, uint64_t offset, QEMUIOVector *qiov, int type, BdrvRequestFlags flags); -void luring_detach_aio_context(LuringState *s, AioContext *old_context); -void luring_attach_aio_context(LuringState *s, AioContext *new_context); bool luring_has_fua(void); #else static inline bool luring_has_fua(void) diff --git a/include/block/snapshot.h b/include/block/snapshot.h index 304cc6e..2316a43 100644 --- a/include/block/snapshot.h +++ b/include/block/snapshot.h @@ -90,9 +90,9 @@ int bdrv_snapshot_load_tmp_by_id_or_name(BlockDriverState *bs, bool bdrv_all_can_snapshot(bool has_devices, strList *devices, Error **errp); -int bdrv_all_delete_snapshot(const char *name, - bool has_devices, strList *devices, - Error **errp); +int GRAPH_UNLOCKED +bdrv_all_delete_snapshot(const char *name, bool has_devices, strList *devices, + Error **errp); int bdrv_all_goto_snapshot(const char *name, bool has_devices, strList *devices, Error **errp); diff --git a/include/chardev/char-fd.h b/include/chardev/char-fd.h index 9de0e44..6fe4306 100644 --- a/include/chardev/char-fd.h +++ b/include/chardev/char-fd.h @@ -41,7 +41,7 @@ typedef struct FDChardev FDChardev; DECLARE_INSTANCE_CHECKER(FDChardev, FD_CHARDEV, TYPE_CHARDEV_FD) -void qemu_chr_open_fd(Chardev *chr, int fd_in, int fd_out); +bool qemu_chr_open_fd(Chardev *chr, int fd_in, int fd_out, Error **errp); int qmp_chardev_open_file_source(char *src, int flags, Error **errp); #endif /* CHAR_FD_H */ diff --git a/include/chardev/char-fe.h b/include/chardev/char-fe.h index 8ef05b3..5f8a6df 100644 --- a/include/chardev/char-fe.h +++ b/include/chardev/char-fe.h @@ -8,12 +8,12 @@ typedef void IOEventHandler(void *opaque, QEMUChrEvent event); typedef int BackendChangeHandler(void *opaque); /** - * struct CharBackend - back end as seen by front end + * struct CharFrontend - Chardev as seen by front end * @fe_is_open: the front end is ready for IO * * The actual backend is Chardev */ -struct CharBackend { +struct CharFrontend { Chardev *chr; IOEventHandler *chr_event; IOCanReadHandler *chr_can_read; @@ -27,53 +27,52 @@ struct CharBackend { /** * qemu_chr_fe_init: * - * Initializes a front end for the given CharBackend and - * Chardev. Call qemu_chr_fe_deinit() to remove the association and - * release the driver. + * Initializes the frontend @c for the given Chardev backend @s. Call + * qemu_chr_fe_deinit() to remove the association and release the backend. * * Returns: false on error. */ -bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp); +bool qemu_chr_fe_init(CharFrontend *c, Chardev *be, Error **errp); /** * qemu_chr_fe_deinit: - * @b: a CharBackend + * @c: a CharFrontend * @del: if true, delete the chardev backend * - * Dissociate the CharBackend from the Chardev. + * Dissociate the CharFrontend from the Chardev. * * Safe to call without associated Chardev. */ -void qemu_chr_fe_deinit(CharBackend *b, bool del); +void qemu_chr_fe_deinit(CharFrontend *c, bool del); /** * qemu_chr_fe_get_driver: * - * Returns: the driver associated with a CharBackend or NULL if no + * Returns: the driver associated with a CharFrontend or NULL if no * associated Chardev. * Note: avoid this function as the driver should never be accessed directly, * especially by the frontends that support chardevice hotswap. * Consider qemu_chr_fe_backend_connected() to check for driver existence */ -Chardev *qemu_chr_fe_get_driver(CharBackend *be); +Chardev *qemu_chr_fe_get_driver(CharFrontend *c); /** * qemu_chr_fe_backend_connected: * - * Returns: true if there is a chardevice associated with @be. + * Returns: true if there is a backend associated with @c. */ -bool qemu_chr_fe_backend_connected(CharBackend *be); +bool qemu_chr_fe_backend_connected(CharFrontend *c); /** * qemu_chr_fe_backend_open: * - * Returns: true if chardevice associated with @be is open. + * Returns: true if the backend associated with @c is open. */ -bool qemu_chr_fe_backend_open(CharBackend *be); +bool qemu_chr_fe_backend_open(CharFrontend *c); /** * qemu_chr_fe_set_handlers_full: - * @b: a CharBackend + * @c: a CharFrontend * @fd_can_read: callback to get the amount of data the frontend may * receive * @fd_read: callback to receive data from char @@ -91,7 +90,7 @@ bool qemu_chr_fe_backend_open(CharBackend *be); * * Without associated Chardev, nothing is changed. */ -void qemu_chr_fe_set_handlers_full(CharBackend *b, +void qemu_chr_fe_set_handlers_full(CharFrontend *c, IOCanReadHandler *fd_can_read, IOReadHandler *fd_read, IOEventHandler *fd_event, @@ -106,7 +105,7 @@ void qemu_chr_fe_set_handlers_full(CharBackend *b, * * Version of qemu_chr_fe_set_handlers_full() with sync_state = true. */ -void qemu_chr_fe_set_handlers(CharBackend *b, +void qemu_chr_fe_set_handlers(CharFrontend *c, IOCanReadHandler *fd_can_read, IOReadHandler *fd_read, IOEventHandler *fd_event, @@ -122,14 +121,14 @@ void qemu_chr_fe_set_handlers(CharBackend *b, * * Without associated Chardev, nothing is changed. */ -void qemu_chr_fe_take_focus(CharBackend *b); +void qemu_chr_fe_take_focus(CharFrontend *c); /** * qemu_chr_fe_accept_input: * * Notify that the frontend is ready to receive data */ -void qemu_chr_fe_accept_input(CharBackend *be); +void qemu_chr_fe_accept_input(CharFrontend *c); /** * qemu_chr_fe_disconnect: @@ -137,7 +136,7 @@ void qemu_chr_fe_accept_input(CharBackend *be); * Close a fd accepted by character backend. * Without associated Chardev, do nothing. */ -void qemu_chr_fe_disconnect(CharBackend *be); +void qemu_chr_fe_disconnect(CharFrontend *c); /** * qemu_chr_fe_wait_connected: @@ -145,7 +144,7 @@ void qemu_chr_fe_disconnect(CharBackend *be); * Wait for character backend to be connected, return < 0 on error or * if no associated Chardev. */ -int qemu_chr_fe_wait_connected(CharBackend *be, Error **errp); +int qemu_chr_fe_wait_connected(CharFrontend *c, Error **errp); /** * qemu_chr_fe_set_echo: @@ -156,17 +155,17 @@ int qemu_chr_fe_wait_connected(CharBackend *be, Error **errp); * can see what you type if you try to type QMP commands. * Without associated Chardev, do nothing. */ -void qemu_chr_fe_set_echo(CharBackend *be, bool echo); +void qemu_chr_fe_set_echo(CharFrontend *c, bool echo); /** * qemu_chr_fe_set_open: - * @be: a CharBackend + * @c: a CharFrontend * @is_open: the front end open status * * This is an indication that the front end is ready (or not) to begin * doing I/O. Without associated Chardev, do nothing. */ -void qemu_chr_fe_set_open(CharBackend *be, bool is_open); +void qemu_chr_fe_set_open(CharFrontend *c, bool is_open); /** * qemu_chr_fe_printf: @@ -176,7 +175,7 @@ void qemu_chr_fe_set_open(CharBackend *be, bool is_open); * function is thread-safe. It does nothing without associated * Chardev. */ -void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...) +void qemu_chr_fe_printf(CharFrontend *c, const char *fmt, ...) G_GNUC_PRINTF(2, 3); @@ -215,7 +214,7 @@ typedef gboolean (*FEWatchFunc)(void *do_not_use, GIOCondition condition, void * * * Returns: the source tag */ -guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond, +guint qemu_chr_fe_add_watch(CharFrontend *c, GIOCondition cond, FEWatchFunc func, void *user_data); /** @@ -230,7 +229,7 @@ guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond, * Returns: the number of bytes consumed (0 if no associated Chardev) * or -1 on error. */ -int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len); +int qemu_chr_fe_write(CharFrontend *c, const uint8_t *buf, int len); /** * qemu_chr_fe_write_all: @@ -245,7 +244,7 @@ int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len); * Returns: the number of bytes consumed (0 if no associated Chardev) * or -1 on error. */ -int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len); +int qemu_chr_fe_write_all(CharFrontend *c, const uint8_t *buf, int len); /** * qemu_chr_fe_read_all: @@ -257,7 +256,7 @@ int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len); * Returns: the number of bytes read (0 if no associated Chardev) * or -1 on error. */ -int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len); +int qemu_chr_fe_read_all(CharFrontend *c, uint8_t *buf, int len); /** * qemu_chr_fe_ioctl: @@ -270,7 +269,7 @@ int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len); * associated Chardev, -ENOTSUP, otherwise the return * value depends on the semantics of @cmd */ -int qemu_chr_fe_ioctl(CharBackend *be, int cmd, void *arg); +int qemu_chr_fe_ioctl(CharFrontend *c, int cmd, void *arg); /** * qemu_chr_fe_get_msgfd: @@ -283,7 +282,7 @@ int qemu_chr_fe_ioctl(CharBackend *be, int cmd, void *arg); * this function will return -1 until a client sends a new file * descriptor. */ -int qemu_chr_fe_get_msgfd(CharBackend *be); +int qemu_chr_fe_get_msgfd(CharFrontend *c); /** * qemu_chr_fe_get_msgfds: @@ -296,7 +295,7 @@ int qemu_chr_fe_get_msgfd(CharBackend *be); * this function will return -1 until a client sends a new set of file * descriptors. */ -int qemu_chr_fe_get_msgfds(CharBackend *be, int *fds, int num); +int qemu_chr_fe_get_msgfds(CharFrontend *c, int *fds, int num); /** * qemu_chr_fe_set_msgfds: @@ -309,6 +308,6 @@ int qemu_chr_fe_get_msgfds(CharBackend *be, int *fds, int num); * * Returns: -1 if fd passing isn't supported or no associated Chardev. */ -int qemu_chr_fe_set_msgfds(CharBackend *be, int *fds, int num); +int qemu_chr_fe_set_msgfds(CharFrontend *c, int *fds, int num); #endif /* QEMU_CHAR_FE_H */ diff --git a/include/chardev/char.h b/include/chardev/char.h index 429852f..b65e998 100644 --- a/include/chardev/char.h +++ b/include/chardev/char.h @@ -15,7 +15,7 @@ #define IAC 255 /* character device */ -typedef struct CharBackend CharBackend; +typedef struct CharFrontend CharFrontend; typedef enum { CHR_EVENT_BREAK, /* serial break char */ @@ -60,7 +60,7 @@ struct Chardev { Object parent_obj; QemuMutex chr_write_lock; - CharBackend *be; + CharFrontend *fe; char *label; char *filename; int logfd; diff --git a/include/crypto/hash.h b/include/crypto/hash.h index 1868d4a..4352509 100644 --- a/include/crypto/hash.h +++ b/include/crypto/hash.h @@ -122,7 +122,7 @@ int qcrypto_hash_bytesv(QCryptoHashAlgo alg, * Returns: 0 on success, -1 on error */ int qcrypto_hash_bytes(QCryptoHashAlgo alg, - const char *buf, + const void *buf, size_t len, uint8_t **result, size_t *resultlen, @@ -180,7 +180,7 @@ int qcrypto_hash_updatev(QCryptoHash *hash, * Returns: 0 on success, -1 on error */ int qcrypto_hash_update(QCryptoHash *hash, - const char *buf, + const void *buf, size_t len, Error **errp); @@ -289,7 +289,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoHash, qcrypto_hash_free) * Returns: 0 on success, -1 on error */ int qcrypto_hash_digest(QCryptoHashAlgo alg, - const char *buf, + const void *buf, size_t len, char **digest, Error **errp); @@ -335,7 +335,7 @@ int qcrypto_hash_base64v(QCryptoHashAlgo alg, * Returns: 0 on success, -1 on error */ int qcrypto_hash_base64(QCryptoHashAlgo alg, - const char *buf, + const void *buf, size_t len, char **base64, Error **errp); diff --git a/include/crypto/hmac.h b/include/crypto/hmac.h index da8a1e3..0885ae2 100644 --- a/include/crypto/hmac.h +++ b/include/crypto/hmac.h @@ -90,6 +90,12 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoHmac, qcrypto_hmac_free) * The memory referenced in @result must be released with a call * to g_free() when no longer required by the caller. * + * If @result_len is set to a NULL pointer, no result will be returned, and + * the hmac object can be used for further invocations of qcrypto_hmac_bytes() + * or qcrypto_hmac_bytesv() until a non-NULL pointer is provided. This allows + * to build the hmac across memory regions that are not available at the same + * time. + * * Returns: * 0 on success, -1 on error */ @@ -123,11 +129,17 @@ int qcrypto_hmac_bytesv(QCryptoHmac *hmac, * The memory referenced in @result must be released with a call * to g_free() when no longer required by the caller. * + * If @result_len is set to a NULL pointer, no result will be returned, and + * the hmac object can be used for further invocations of qcrypto_hmac_bytes() + * or qcrypto_hmac_bytesv() until a non-NULL pointer is provided. This allows + * to build the hmac across memory regions that are not available at the same + * time. + * * Returns: * 0 on success, -1 on error */ int qcrypto_hmac_bytes(QCryptoHmac *hmac, - const char *buf, + const void *buf, size_t len, uint8_t **result, size_t *resultlen, @@ -175,7 +187,7 @@ int qcrypto_hmac_digestv(QCryptoHmac *hmac, * Returns: 0 on success, -1 on error */ int qcrypto_hmac_digest(QCryptoHmac *hmac, - const char *buf, + const void *buf, size_t len, char **digest, Error **errp); diff --git a/include/crypto/tlscreds.h b/include/crypto/tlscreds.h index 2a8a857..bb9280e 100644 --- a/include/crypto/tlscreds.h +++ b/include/crypto/tlscreds.h @@ -47,6 +47,7 @@ typedef bool (*CryptoTLSCredsReload)(QCryptoTLSCreds *, Error **); struct QCryptoTLSCredsClass { ObjectClass parent_class; CryptoTLSCredsReload reload; + const char *prioritySuffix; }; /** @@ -64,4 +65,29 @@ bool qcrypto_tls_creds_check_endpoint(QCryptoTLSCreds *creds, QCryptoTLSCredsEndpoint endpoint, Error **errp); + +/** + * qcrypto_tls_creds_get_priority: + * @creds: pointer to a TLS credentials object + * + * Get the TLS credentials priority string. The caller + * must free the returned string when no longer required. + * + * Returns: a non-NULL priority string + */ +char *qcrypto_tls_creds_get_priority(QCryptoTLSCreds *creds); + + +/** + * qcrypto_tls_creds_reload: + * @creds: pointer to a TLS credentials object + * @errp: pointer to a NULL-initialized error object + * + * Request a reload of the TLS credentials, if supported + * + * Returns: true on success, false on error or if not supported + */ +bool qcrypto_tls_creds_reload(QCryptoTLSCreds *creds, + Error **errp); + #endif /* QCRYPTO_TLSCREDS_H */ diff --git a/include/crypto/tlscredsx509.h b/include/crypto/tlscredsx509.h index c4daba2..61b7f73 100644 --- a/include/crypto/tlscredsx509.h +++ b/include/crypto/tlscredsx509.h @@ -37,7 +37,13 @@ typedef struct QCryptoTLSCredsX509Class QCryptoTLSCredsX509Class; #define QCRYPTO_TLS_CREDS_X509_SERVER_CERT "server-cert.pem" #define QCRYPTO_TLS_CREDS_X509_CLIENT_KEY "client-key.pem" #define QCRYPTO_TLS_CREDS_X509_CLIENT_CERT "client-cert.pem" +#define QCRYPTO_TLS_CREDS_X509_SERVER_KEY_N "server-key-%zu.pem" +#define QCRYPTO_TLS_CREDS_X509_SERVER_CERT_N "server-cert-%zu.pem" +#define QCRYPTO_TLS_CREDS_X509_CLIENT_KEY_N "client-key-%zu.pem" +#define QCRYPTO_TLS_CREDS_X509_CLIENT_CERT_N "client-cert-%zu.pem" +/* Max number of additional cert/key pairs (ie _N constants) */ +#define QCRYPTO_TLS_CREDS_X509_IDENTITY_MAX 4 /** * QCryptoTLSCredsX509: diff --git a/include/crypto/tlssession.h b/include/crypto/tlssession.h index d77ae0d..28e4196 100644 --- a/include/crypto/tlssession.h +++ b/include/crypto/tlssession.h @@ -110,6 +110,7 @@ typedef struct QCryptoTLSSession QCryptoTLSSession; #define QCRYPTO_TLS_SESSION_ERR_BLOCK -2 +#define QCRYPTO_TLS_SESSION_PREMATURE_TERMINATION -3 /** * qcrypto_tls_session_new: @@ -166,6 +167,20 @@ void qcrypto_tls_session_free(QCryptoTLSSession *sess); G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoTLSSession, qcrypto_tls_session_free) /** + * qcrypto_tls_session_require_thread_safety: + * @sess: the TLS session object + * + * Mark that this TLS session will require thread safety + * for concurrent I/O in both directions. This must be + * called before the handshake is performed. + * + * This will activate a workaround for GNUTLS thread + * safety issues, where appropriate for the negotiated + * TLS session parameters. + */ +void qcrypto_tls_session_require_thread_safety(QCryptoTLSSession *sess); + +/** * qcrypto_tls_session_check_credentials: * @sess: the TLS session object * @errp: pointer to a NULL-initialized error object @@ -184,11 +199,11 @@ int qcrypto_tls_session_check_credentials(QCryptoTLSSession *sess, * These must return QCRYPTO_TLS_SESSION_ERR_BLOCK if the I/O * would block, but on other errors, must fill 'errp' */ -typedef ssize_t (*QCryptoTLSSessionWriteFunc)(const char *buf, +typedef ssize_t (*QCryptoTLSSessionWriteFunc)(const void *buf, size_t len, void *opaque, Error **errp); -typedef ssize_t (*QCryptoTLSSessionReadFunc)(char *buf, +typedef ssize_t (*QCryptoTLSSessionReadFunc)(void *buf, size_t len, void *opaque, Error **errp); @@ -245,7 +260,6 @@ ssize_t qcrypto_tls_session_write(QCryptoTLSSession *sess, * @sess: the TLS session object * @buf: to fill with plain text received * @len: the length of @buf - * @gracefulTermination: treat premature termination as graceful EOF * @errp: pointer to hold returned error object * * Receive up to @len bytes of data from the remote peer @@ -253,22 +267,18 @@ ssize_t qcrypto_tls_session_write(QCryptoTLSSession *sess, * qcrypto_tls_session_set_callbacks(), decrypt it and * store it in @buf. * - * If @gracefulTermination is true, then a premature termination - * of the TLS session will be treated as indicating EOF, as - * opposed to an error. - * * It is an error to call this before * qcrypto_tls_session_handshake() returns * QCRYPTO_TLS_HANDSHAKE_COMPLETE * * Returns: the number of bytes received, * or QCRYPTO_TLS_SESSION_ERR_BLOCK if the receive would block, - * or -1 on error. + * or QCRYPTO_TLS_SESSION_PREMATURE_TERMINATION if a premature termination + * is detected, or -1 on error. */ ssize_t qcrypto_tls_session_read(QCryptoTLSSession *sess, char *buf, size_t len, - bool gracefulTermination, Error **errp); /** diff --git a/include/crypto/xts.h b/include/crypto/xts.h deleted file mode 100644 index f267b78..0000000 --- a/include/crypto/xts.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * QEMU Crypto XTS cipher mode - * - * Copyright (c) 2015-2016 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/>. - * - * This code is originally derived from public domain / WTFPL code in - * LibTomCrypt crytographic library http://libtom.org. The XTS code - * was donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) - * to the LibTom Projects - * - */ - -#ifndef QCRYPTO_XTS_H -#define QCRYPTO_XTS_H - - -#define XTS_BLOCK_SIZE 16 - -typedef void xts_cipher_func(const void *ctx, - size_t length, - uint8_t *dst, - const uint8_t *src); - -/** - * xts_decrypt: - * @datactx: the cipher context for data decryption - * @tweakctx: the cipher context for tweak decryption - * @encfunc: the cipher function for encryption - * @decfunc: the cipher function for decryption - * @iv: the initialization vector tweak of XTS_BLOCK_SIZE bytes - * @length: the length of @dst and @src - * @dst: buffer to hold the decrypted plaintext - * @src: buffer providing the ciphertext - * - * Decrypts @src into @dst - */ -void xts_decrypt(const void *datactx, - const void *tweakctx, - xts_cipher_func *encfunc, - xts_cipher_func *decfunc, - uint8_t *iv, - size_t length, - uint8_t *dst, - const uint8_t *src); - -/** - * xts_decrypt: - * @datactx: the cipher context for data encryption - * @tweakctx: the cipher context for tweak encryption - * @encfunc: the cipher function for encryption - * @decfunc: the cipher function for decryption - * @iv: the initialization vector tweak of XTS_BLOCK_SIZE bytes - * @length: the length of @dst and @src - * @dst: buffer to hold the encrypted ciphertext - * @src: buffer providing the plaintext - * - * Decrypts @src into @dst - */ -void xts_encrypt(const void *datactx, - const void *tweakctx, - xts_cipher_func *encfunc, - xts_cipher_func *decfunc, - uint8_t *iv, - size_t length, - uint8_t *dst, - const uint8_t *src); - - -#endif /* QCRYPTO_XTS_H */ diff --git a/include/elf.h b/include/elf.h index e7259ec..bbfac05 100644 --- a/include/elf.h +++ b/include/elf.h @@ -56,6 +56,13 @@ typedef int64_t Elf64_Sxword; #define EF_MIPS_ARCH_32R6 0x90000000 /* MIPS32r6 code. */ #define EF_MIPS_ARCH_64R6 0xa0000000 /* MIPS64r6 code. */ +/* MIPS Architectural Extensions. */ +#define EF_MIPS_ARCH_ASE 0x0f000000 + +#define EF_MIPS_ARCH_ASE_MICROMIPS 0x02000000 +#define EF_MIPS_ARCH_ASE_M16 0x04000000 +#define EF_MIPS_ARCH_ASE_MDMX 0x08000000 + /* The ABI of a file. */ #define EF_MIPS_ABI_O32 0x00001000 /* O32 ABI. */ #define EF_MIPS_ABI_O64 0x00002000 /* O32 extended for 64 bit. */ diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index a684855..e0be4ee 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -85,6 +85,7 @@ void qemu_ram_unset_idstr(RAMBlock *block); const char *qemu_ram_get_idstr(RAMBlock *rb); void *qemu_ram_get_host_addr(RAMBlock *rb); ram_addr_t qemu_ram_get_offset(RAMBlock *rb); +ram_addr_t qemu_ram_get_fd_offset(RAMBlock *rb); ram_addr_t qemu_ram_get_used_length(RAMBlock *rb); ram_addr_t qemu_ram_get_max_length(RAMBlock *rb); bool qemu_ram_is_shared(RAMBlock *rb); @@ -122,34 +123,22 @@ size_t qemu_ram_pagesize_largest(void); void cpu_address_space_init(CPUState *cpu, int asidx, const char *prefix, MemoryRegion *mr); /** - * cpu_address_space_destroy: - * @cpu: CPU for which address space needs to be destroyed - * @asidx: integer index of this address space + * cpu_destroy_address_spaces: + * @cpu: CPU for which address spaces need to be destroyed * - * Note that with KVM only one address space is supported. + * Destroy all address spaces associated with this CPU; this + * is called as part of unrealizing the CPU. */ -void cpu_address_space_destroy(CPUState *cpu, int asidx); +void cpu_destroy_address_spaces(CPUState *cpu); -void cpu_physical_memory_rw(hwaddr addr, void *buf, - hwaddr len, bool is_write); -static inline void cpu_physical_memory_read(hwaddr addr, - void *buf, hwaddr len) -{ - cpu_physical_memory_rw(addr, buf, len, false); -} -static inline void cpu_physical_memory_write(hwaddr addr, - const void *buf, hwaddr len) -{ - cpu_physical_memory_rw(addr, (void *)buf, len, true); -} +void cpu_physical_memory_read(hwaddr addr, void *buf, hwaddr len); +void cpu_physical_memory_write(hwaddr addr, const void *buf, hwaddr len); void *cpu_physical_memory_map(hwaddr addr, hwaddr *plen, bool is_write); void cpu_physical_memory_unmap(void *buffer, hwaddr len, bool is_write, hwaddr access_len); -bool cpu_physical_memory_is_io(hwaddr phys_addr); - /* Coalesced MMIO regions are areas where write operations can be reordered. * This usually implies that write operations are side-effect free. This allows * batching which can make a major impact on performance when using @@ -157,18 +146,9 @@ bool cpu_physical_memory_is_io(hwaddr phys_addr); */ void qemu_flush_coalesced_mmio_buffer(void); -void cpu_flush_icache_range(hwaddr start, hwaddr len); - typedef int (RAMBlockIterFunc)(RAMBlock *rb, void *opaque); int qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque); -int ram_block_discard_range(RAMBlock *rb, uint64_t start, size_t length); -int ram_block_discard_guest_memfd_range(RAMBlock *rb, uint64_t start, - size_t length); - -/* Returns: 0 on success, -1 on error */ -int cpu_memory_rw_debug(CPUState *cpu, vaddr addr, - void *ptr, size_t len, bool is_write); /* vl.c */ void list_cpus(void); @@ -220,9 +200,9 @@ static inline bool cpu_loop_exit_requested(CPUState *cpu) G_NORETURN void cpu_loop_exit_noexc(CPUState *cpu); G_NORETURN void cpu_loop_exit_atomic(CPUState *cpu, uintptr_t pc); +G_NORETURN void cpu_loop_exit_restore(CPUState *cpu, uintptr_t pc); #endif /* CONFIG_TCG */ G_NORETURN void cpu_loop_exit(CPUState *cpu); -G_NORETURN void cpu_loop_exit_restore(CPUState *cpu, uintptr_t pc); /* accel/tcg/cpu-exec.c */ int cpu_exec(CPUState *cpu); diff --git a/include/exec/cputlb.h b/include/exec/cputlb.h index 03ed7e2..9bec0e7 100644 --- a/include/exec/cputlb.h +++ b/include/exec/cputlb.h @@ -150,7 +150,7 @@ void tlb_flush_all_cpus_synced(CPUState *src_cpu); * MMU indexes. */ void tlb_flush_page_by_mmuidx(CPUState *cpu, vaddr addr, - uint16_t idxmap); + MMUIdxMap idxmap); /** * tlb_flush_page_by_mmuidx_all_cpus_synced: @@ -165,7 +165,7 @@ void tlb_flush_page_by_mmuidx(CPUState *cpu, vaddr addr, * translations using the flushed TLBs. */ void tlb_flush_page_by_mmuidx_all_cpus_synced(CPUState *cpu, vaddr addr, - uint16_t idxmap); + MMUIdxMap idxmap); /** * tlb_flush_by_mmuidx: @@ -176,7 +176,7 @@ void tlb_flush_page_by_mmuidx_all_cpus_synced(CPUState *cpu, vaddr addr, * Flush all entries from the TLB of the specified CPU, for the specified * MMU indexes. */ -void tlb_flush_by_mmuidx(CPUState *cpu, uint16_t idxmap); +void tlb_flush_by_mmuidx(CPUState *cpu, MMUIdxMap idxmap); /** * tlb_flush_by_mmuidx_all_cpus_synced: @@ -189,7 +189,7 @@ void tlb_flush_by_mmuidx(CPUState *cpu, uint16_t idxmap); * When this function returns, no CPUs will subsequently perform * translations using the flushed TLBs. */ -void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu, uint16_t idxmap); +void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu, MMUIdxMap idxmap); /** * tlb_flush_page_bits_by_mmuidx @@ -201,11 +201,11 @@ void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu, uint16_t idxmap); * Similar to tlb_flush_page_mask, but with a bitmap of indexes. */ void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, vaddr addr, - uint16_t idxmap, unsigned bits); + MMUIdxMap idxmap, unsigned bits); /* Similarly, with broadcast and syncing. */ void tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *cpu, vaddr addr, - uint16_t idxmap, + MMUIdxMap idxmap, unsigned bits); /** @@ -220,14 +220,14 @@ void tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *cpu, vaddr addr, * comparing only the low @bits worth of each virtual page. */ void tlb_flush_range_by_mmuidx(CPUState *cpu, vaddr addr, - vaddr len, uint16_t idxmap, + vaddr len, MMUIdxMap idxmap, unsigned bits); /* Similarly, with broadcast and syncing. */ void tlb_flush_range_by_mmuidx_all_cpus_synced(CPUState *cpu, vaddr addr, vaddr len, - uint16_t idxmap, + MMUIdxMap idxmap, unsigned bits); #else static inline void tlb_flush_page(CPUState *cpu, vaddr addr) @@ -243,42 +243,42 @@ static inline void tlb_flush_all_cpus_synced(CPUState *src_cpu) { } static inline void tlb_flush_page_by_mmuidx(CPUState *cpu, - vaddr addr, uint16_t idxmap) + vaddr addr, MMUIdxMap idxmap) { } -static inline void tlb_flush_by_mmuidx(CPUState *cpu, uint16_t idxmap) +static inline void tlb_flush_by_mmuidx(CPUState *cpu, MMUIdxMap idxmap) { } static inline void tlb_flush_page_by_mmuidx_all_cpus_synced(CPUState *cpu, vaddr addr, - uint16_t idxmap) + MMUIdxMap idxmap) { } static inline void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu, - uint16_t idxmap) + MMUIdxMap idxmap) { } static inline void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, vaddr addr, - uint16_t idxmap, + MMUIdxMap idxmap, unsigned bits) { } static inline void tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *cpu, vaddr addr, - uint16_t idxmap, unsigned bits) + MMUIdxMap idxmap, unsigned bits) { } static inline void tlb_flush_range_by_mmuidx(CPUState *cpu, vaddr addr, - vaddr len, uint16_t idxmap, + vaddr len, MMUIdxMap idxmap, unsigned bits) { } static inline void tlb_flush_range_by_mmuidx_all_cpus_synced(CPUState *cpu, vaddr addr, vaddr len, - uint16_t idxmap, + MMUIdxMap idxmap, unsigned bits) { } diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h index 0675b0b..bd7182c 100644 --- a/include/exec/gdbstub.h +++ b/include/exec/gdbstub.h @@ -55,9 +55,6 @@ void gdb_unregister_coprocessor_all(CPUState *cpu); * system emulation you can use a full chardev spec for your gdbserver * port. * - * The error handle should be either &error_fatal (for start-up) or - * &error_warn (for QMP/HMP initiated sessions). - * * Returns true when server successfully started. */ bool gdbserver_start(const char *port_or_device, Error **errp); @@ -125,6 +122,20 @@ const GDBFeature *gdb_find_static_feature(const char *xmlname); int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg); /** + * gdb_write_register() - Write a register associated with a CPU. + * @cpu: The CPU associated with the register. + * @buf: The buffer that the register contents will be set to. + * @reg: The register's number returned by gdb_find_feature_register(). + * + * The size of @buf must be at least the size of the register being + * written. + * + * Return: The number of written bytes, or 0 if an error occurred (for + * example, an unknown register was provided). + */ +int gdb_write_register(CPUState *cpu, uint8_t *mem_buf, int reg); + +/** * typedef GDBRegDesc - a register description from gdbstub */ typedef struct { diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h index 8db1d30..52ee955 100644 --- a/include/exec/memattrs.h +++ b/include/exec/memattrs.h @@ -54,6 +54,9 @@ typedef struct MemTxAttrs { */ unsigned int pid:8; + /* PCI - IOMMU operations, see PCIAddressType */ + unsigned int address_type:1; + /* * Bus masters which don't specify any attributes will get this * (via the MEMTXATTRS_UNSPECIFIED constant), so that we can diff --git a/include/exec/memop.h b/include/exec/memop.h index 407a47d..799b5b4 100644 --- a/include/exec/memop.h +++ b/include/exec/memop.h @@ -73,6 +73,16 @@ typedef enum MemOp { MO_ALIGN = MO_AMASK, /* + * MO_ALIGN_TLB_ONLY: + * Apply MO_AMASK only along the TCG slow path if TLB_CHECK_ALIGNED + * is set; otherwise unaligned access is permitted. + * This is used by target/arm, where unaligned accesses are + * permitted for pages marked Normal but aligned accesses are + * required for pages marked Device. + */ + MO_ALIGN_TLB_ONLY = 1 << 8, + + /* * MO_ATOM_* describes the atomicity requirements of the operation: * MO_ATOM_IFALIGN: the operation must be single-copy atomic if it * is aligned; if unaligned there is no atomicity. @@ -104,7 +114,7 @@ typedef enum MemOp { * size of the operation, if aligned. This retains the behaviour * from before this field was introduced. */ - MO_ATOM_SHIFT = 8, + MO_ATOM_SHIFT = 9, MO_ATOM_IFALIGN = 0 << MO_ATOM_SHIFT, MO_ATOM_IFALIGN_PAIR = 1 << MO_ATOM_SHIFT, MO_ATOM_WITHIN16 = 2 << MO_ATOM_SHIFT, @@ -162,23 +172,23 @@ static inline unsigned memop_size(MemOp op) static inline MemOp size_memop(unsigned size) { #ifdef CONFIG_DEBUG_TCG - /* Power of 2 up to 8. */ - assert((size & (size - 1)) == 0 && size >= 1 && size <= 8); + /* Power of 2 up to 1024 */ + assert(is_power_of_2(size) && size >= 1 && size <= (1 << MO_SIZE)); #endif return (MemOp)ctz32(size); } /** - * memop_alignment_bits: + * memop_tlb_alignment_bits: * @memop: MemOp value * - * Extract the alignment size from the memop. + * Extract the alignment size for use with TLB_CHECK_ALIGNED. */ -static inline unsigned memop_alignment_bits(MemOp memop) +static inline unsigned memop_tlb_alignment_bits(MemOp memop, bool tlb_check) { unsigned a = memop & MO_AMASK; - if (a == MO_UNALN) { + if (a == MO_UNALN || (!tlb_check && (memop & MO_ALIGN_TLB_ONLY))) { /* No alignment required. */ a = 0; } else if (a == MO_ALIGN) { @@ -191,28 +201,15 @@ static inline unsigned memop_alignment_bits(MemOp memop) return a; } -/* - * memop_atomicity_bits: +/** + * memop_alignment_bits: * @memop: MemOp value * - * Extract the atomicity size from the memop. + * Extract the alignment size from the memop. */ -static inline unsigned memop_atomicity_bits(MemOp memop) +static inline unsigned memop_alignment_bits(MemOp memop) { - unsigned size = memop & MO_SIZE; - - switch (memop & MO_ATOM_MASK) { - case MO_ATOM_NONE: - size = MO_8; - break; - case MO_ATOM_IFALIGN_PAIR: - case MO_ATOM_WITHIN16_PAIR: - size = size ? size - 1 : 0; - break; - default: - break; - } - return size; + return memop_tlb_alignment_bits(memop, false); } #endif diff --git a/include/exec/memopidx.h b/include/exec/memopidx.h index eb7f159..66d9c58 100644 --- a/include/exec/memopidx.h +++ b/include/exec/memopidx.h @@ -25,9 +25,10 @@ typedef uint32_t MemOpIdx; static inline MemOpIdx make_memop_idx(MemOp op, unsigned idx) { #ifdef CONFIG_DEBUG_TCG - assert(idx <= 15); + assert(idx <= 31); + assert(clz32(op) >= 5); #endif - return (op << 4) | idx; + return (op << 5) | idx; } /** @@ -38,7 +39,7 @@ static inline MemOpIdx make_memop_idx(MemOp op, unsigned idx) */ static inline MemOp get_memop(MemOpIdx oi) { - return oi >> 4; + return oi >> 5; } /** @@ -49,7 +50,7 @@ static inline MemOp get_memop(MemOpIdx oi) */ static inline unsigned get_mmuidx(MemOpIdx oi) { - return oi & 15; + return oi & 31; } #endif diff --git a/include/exec/page-protection.h b/include/exec/page-protection.h index c43231a..c50ce57 100644 --- a/include/exec/page-protection.h +++ b/include/exec/page-protection.h @@ -23,19 +23,20 @@ * Low-Address-Protection. Used with PAGE_WRITE in tlb_set_page_with_attrs() */ #define PAGE_WRITE_INV 0x0020 -/* For use with page_set_flags: page is being replaced; target_data cleared. */ -#define PAGE_RESET 0x0040 +/* + * For linux-user, indicates that the page is mapped with the same semantics + * in both guest and host. + */ +#define PAGE_PASSTHROUGH 0x40 /* For linux-user, indicates that the page is MAP_ANON. */ #define PAGE_ANON 0x0080 - +/* + * For linux-user, indicates that the page should not be + * included in a core dump. + */ +#define PAGE_DONTDUMP 0x0100 /* Target-specific bits that will be used via page_get_flags(). */ #define PAGE_TARGET_1 0x0200 #define PAGE_TARGET_2 0x0400 -/* - * For linux-user, indicates that the page is mapped with the same semantics - * in both guest and host. - */ -#define PAGE_PASSTHROUGH 0x0800 - #endif diff --git a/include/exec/target_page.h b/include/exec/target_page.h index ca0ebbc..813591c 100644 --- a/include/exec/target_page.h +++ b/include/exec/target_page.h @@ -62,6 +62,15 @@ static inline int qemu_target_page_bits(void) return TARGET_PAGE_BITS; } -size_t qemu_target_pages_to_MiB(size_t pages); +/* Convert target pages to MiB (2**20). */ +static inline size_t qemu_target_pages_to_MiB(size_t pages) +{ + int page_bits = TARGET_PAGE_BITS; + + /* So far, the largest (non-huge) page size is 64k, i.e. 16 bits. */ + g_assert(page_bits < 20); + + return pages >> (20 - page_bits); +} #endif diff --git a/include/exec/tb-flush.h b/include/exec/tb-flush.h index 142c240..e971d4b 100644 --- a/include/exec/tb-flush.h +++ b/include/exec/tb-flush.h @@ -9,19 +9,29 @@ #define _TB_FLUSH_H_ /** - * tb_flush() - flush all translation blocks - * @cs: CPUState (must be valid, but treated as anonymous pointer) + * tb_flush__exclusive_or_serial() * - * Used to flush all the translation blocks in the system. Sometimes - * it is simpler to flush everything than work out which individual - * translations are now invalid and ensure they are not called - * anymore. + * Used to flush all the translation blocks in the system. Mostly this is + * used to empty the code generation buffer after it is full. Sometimes it + * is used when it is simpler to flush everything than work out which + * individual translations are now invalid. * - * tb_flush() takes care of running the flush in an exclusive context - * if it is not already running in one. This means no guest code will - * run until this complete. + * Must be called from an exclusive or serial context, e.g. start_exclusive, + * vm_stop, or when there is only one vcpu. Note that start_exclusive cannot + * be called from within the cpu run loop, so this cannot be called from + * within target code. */ -void tb_flush(CPUState *cs); +void tb_flush__exclusive_or_serial(void); + +/** + * queue_tb_flush() - add flush to the cpu work queue + * @cs: CPUState + * + * Flush all translation blocks the next time @cs processes the work queue. + * This should generally be followed by cpu_loop_exit(), so that the work + * queue is processed promptly. + */ +void queue_tb_flush(CPUState *cs); void tcg_flush_jmp_cache(CPUState *cs); diff --git a/include/exec/tswap.h b/include/exec/tswap.h index 49511f2..72219e2 100644 --- a/include/exec/tswap.h +++ b/include/exec/tswap.h @@ -9,18 +9,7 @@ #define TSWAP_H #include "qemu/bswap.h" - -/** - * target_big_endian: - * Returns true if the (default) endianness of the target is big endian, - * false otherwise. Common code should normally never need to know about the - * endianness of the target, so please do *not* use this function unless you - * know very well what you are doing! - */ -bool target_big_endian(void); -#ifdef COMPILING_PER_TARGET -#define target_big_endian() TARGET_BIG_ENDIAN -#endif +#include "qemu/target-info.h" /* * If we're in target-specific code, we can hard-code the swapping @@ -80,74 +69,4 @@ static inline void tswap64s(uint64_t *s) } } -/* 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 /* TSWAP_H */ diff --git a/include/gdbstub/commands.h b/include/gdbstub/commands.h index 40f0514..bff3674 100644 --- a/include/gdbstub/commands.h +++ b/include/gdbstub/commands.h @@ -1,5 +1,5 @@ #ifndef GDBSTUB_COMMANDS_H -#define GDBSTUB +#define GDBSTUB_COMMANDS_H typedef void (*GdbCmdHandler)(GArray *params, void *user_ctx); diff --git a/include/gdbstub/helpers.h b/include/gdbstub/helpers.h index 6f7cc48..b685afa 100644 --- a/include/gdbstub/helpers.h +++ b/include/gdbstub/helpers.h @@ -16,7 +16,8 @@ #error "gdbstub helpers should only be included by target specific code" #endif -#include "exec/tswap.h" +#include "qemu/bswap.h" +#include "qemu/target-info.h" #include "cpu-param.h" /* @@ -33,40 +34,49 @@ static inline int gdb_get_reg8(GByteArray *buf, uint8_t val) static inline int gdb_get_reg16(GByteArray *buf, uint16_t val) { - uint16_t to_word = tswap16(val); - g_byte_array_append(buf, (uint8_t *) &to_word, 2); + if (target_big_endian()) { + cpu_to_be16s(&val); + } else { + cpu_to_le16s(&val); + } + g_byte_array_append(buf, (uint8_t *) &val, 2); return 2; } static inline int gdb_get_reg32(GByteArray *buf, uint32_t val) { - uint32_t to_long = tswap32(val); - g_byte_array_append(buf, (uint8_t *) &to_long, 4); + if (target_big_endian()) { + cpu_to_be32s(&val); + } else { + cpu_to_le32s(&val); + } + g_byte_array_append(buf, (uint8_t *) &val, 4); return 4; } static inline int gdb_get_reg64(GByteArray *buf, uint64_t val) { - uint64_t to_quad = tswap64(val); - g_byte_array_append(buf, (uint8_t *) &to_quad, 8); + if (target_big_endian()) { + cpu_to_be64s(&val); + } else { + cpu_to_le64s(&val); + } + g_byte_array_append(buf, (uint8_t *) &val, 8); return 8; } static inline int gdb_get_reg128(GByteArray *buf, uint64_t val_hi, uint64_t val_lo) { - uint64_t to_quad; -#if TARGET_BIG_ENDIAN - to_quad = tswap64(val_hi); - g_byte_array_append(buf, (uint8_t *) &to_quad, 8); - to_quad = tswap64(val_lo); - g_byte_array_append(buf, (uint8_t *) &to_quad, 8); -#else - to_quad = tswap64(val_lo); - g_byte_array_append(buf, (uint8_t *) &to_quad, 8); - to_quad = tswap64(val_hi); - g_byte_array_append(buf, (uint8_t *) &to_quad, 8); -#endif + uint64_t tmp[2]; + if (target_big_endian()) { + tmp[0] = cpu_to_be64(val_hi); + tmp[1] = cpu_to_be64(val_lo); + } else { + tmp[0] = cpu_to_le64(val_lo); + tmp[1] = cpu_to_le64(val_hi); + } + g_byte_array_append(buf, (uint8_t *)&tmp, 16); return 16; } diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_dev_interface.h index 68d9d15..8294f8f 100644 --- a/include/hw/acpi/acpi_dev_interface.h +++ b/include/hw/acpi/acpi_dev_interface.h @@ -13,6 +13,7 @@ typedef enum { ACPI_NVDIMM_HOTPLUG_STATUS = 16, ACPI_VMGENID_CHANGE_STATUS = 32, ACPI_POWER_DOWN_STATUS = 64, + ACPI_GENERIC_ERROR = 128, } AcpiEventStatusBits; #define TYPE_ACPI_DEVICE_IF "acpi-device-interface" diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h index c18f681..f38e129 100644 --- a/include/hw/acpi/aml-build.h +++ b/include/hw/acpi/aml-build.h @@ -252,6 +252,7 @@ struct CrsRangeSet { /* Consumer/Producer */ #define AML_SERIAL_BUS_FLAG_CONSUME_ONLY (1 << 1) +#define ACPI_APEI_ERROR_DEVICE "GEDD" /** * init_aml_allocator: * @@ -382,6 +383,7 @@ Aml *aml_dma(AmlDmaType typ, AmlDmaBusMaster bm, AmlTransferSize sz, uint8_t channel); Aml *aml_sleep(uint64_t msec); Aml *aml_i2c_serial_bus_device(uint16_t address, const char *resource_source); +Aml *aml_error_device(void); /* Block AML object primitives */ Aml *aml_scope(const char *name_format, ...) G_GNUC_PRINTF(1, 2); diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h index d2dac87..130c014 100644 --- a/include/hw/acpi/generic_event_device.h +++ b/include/hw/acpi/generic_event_device.h @@ -63,12 +63,13 @@ #include "hw/acpi/memory_hotplug.h" #include "hw/acpi/ghes.h" #include "hw/acpi/cpu.h" +#include "hw/acpi/pcihp.h" #include "qom/object.h" #define ACPI_POWER_BUTTON_DEVICE "PWRB" #define TYPE_ACPI_GED "acpi-ged" -OBJECT_DECLARE_SIMPLE_TYPE(AcpiGedState, ACPI_GED) +OBJECT_DECLARE_TYPE(AcpiGedState, AcpiGedClass, ACPI_GED) #define ACPI_GED_EVT_SEL_OFFSET 0x0 #define ACPI_GED_EVT_SEL_LEN 0x4 @@ -101,6 +102,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(AcpiGedState, ACPI_GED) #define ACPI_GED_PWR_DOWN_EVT 0x2 #define ACPI_GED_NVDIMM_HOTPLUG_EVT 0x4 #define ACPI_GED_CPU_HOTPLUG_EVT 0x8 +#define ACPI_GED_PCI_HOTPLUG_EVT 0x10 +#define ACPI_GED_ERROR_EVT 0x20 typedef struct GEDState { MemoryRegion evt; @@ -108,18 +111,31 @@ typedef struct GEDState { uint32_t sel; } GEDState; +#define ACPI_PCIHP_REGION_NAME "pcihp container" +#define ACPI_MEMHP_REGION_NAME "memhp container" + struct AcpiGedState { SysBusDevice parent_obj; MemHotplugState memhp_state; MemoryRegion container_memhp; CPUHotplugState cpuhp_state; MemoryRegion container_cpuhp; + AcpiPciHpState pcihp_state; + MemoryRegion container_pcihp; GEDState ged_state; uint32_t ged_event_bitmap; qemu_irq irq; AcpiGhesState ghes_state; }; +typedef struct AcpiGedClass { + /* <private> */ + SysBusDeviceClass parent_class; + + /*< public >*/ + ResettablePhases parent_phases; +} AcpiGedClass; + void build_ged_aml(Aml *table, const char* name, HotplugHandler *hotplug_dev, uint32_t ged_irq, AmlRegionSpace rs, hwaddr ged_base); void acpi_dsdt_add_power_button(Aml *scope); diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h index 578a582..df2ecbf 100644 --- a/include/hw/acpi/ghes.h +++ b/include/hw/acpi/ghes.h @@ -24,6 +24,9 @@ #include "hw/acpi/bios-linker-loader.h" #include "qapi/error.h" +#include "qemu/notify.h" + +extern NotifierList acpi_generic_error_notifiers; /* * Values for Hardware Error Notification Type field @@ -57,30 +60,54 @@ enum AcpiGhesNotifyType { ACPI_GHES_NOTIFY_RESERVED = 12 }; -enum { - ACPI_HEST_SRC_ID_SEA = 0, - /* future ids go here */ - - ACPI_GHES_ERROR_SOURCE_COUNT +/* + * ID numbers used to fill HEST source ID field + */ +enum AcpiGhesSourceID { + ACPI_HEST_SRC_ID_SYNC, + ACPI_HEST_SRC_ID_QMP, /* Use it only for QMP injected errors */ }; +typedef struct AcpiNotificationSourceId { + enum AcpiGhesSourceID source_id; + enum AcpiGhesNotifyType notify; +} AcpiNotificationSourceId; + +/* + * AcpiGhesState stores GPA values that will be used to fill HEST entries. + * + * When use_hest_addr is false, the GPA of the etc/hardware_errors firmware + * is stored at hw_error_le. This is the default on QEMU 9.x. + * + * When use_hest_addr is true, the GPA of the HEST table is stored at + * hest_addr_le. This is the default for QEMU 10.x and above. + * + * Whe both GPA values are equal to zero means that GHES is not present. + */ typedef struct AcpiGhesState { + uint64_t hest_addr_le; uint64_t hw_error_le; - bool present; /* True if GHES is present at all on this board */ + bool use_hest_addr; /* True if HEST address is present */ } AcpiGhesState; -void acpi_build_hest(GArray *table_data, GArray *hardware_errors, +void acpi_build_hest(AcpiGhesState *ags, GArray *table_data, + GArray *hardware_errors, BIOSLinker *linker, + const AcpiNotificationSourceId * const notif_source, + int num_sources, const char *oem_id, const char *oem_table_id); void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s, GArray *hardware_errors); -int acpi_ghes_memory_errors(uint16_t source_id, uint64_t error_physical_addr); +int acpi_ghes_memory_errors(AcpiGhesState *ags, uint16_t source_id, + uint64_t error_physical_addr); +void ghes_record_cper_errors(AcpiGhesState *ags, const void *cper, size_t len, + uint16_t source_id, Error **errp); /** - * acpi_ghes_present: Report whether ACPI GHES table is present + * acpi_ghes_get_state: Get a pointer for ACPI ghes state * - * Returns: true if the system has an ACPI GHES table and it is - * safe to call acpi_ghes_memory_errors() to record a memory error. + * Returns: a pointer to ghes state if the system has an ACPI GHES table, + * NULL, otherwise. */ -bool acpi_ghes_present(void); +AcpiGhesState *acpi_ghes_get_state(void); #endif diff --git a/include/hw/acpi/pci.h b/include/hw/acpi/pci.h index 6359d57..20b6725 100644 --- a/include/hw/acpi/pci.h +++ b/include/hw/acpi/pci.h @@ -36,11 +36,12 @@ typedef struct AcpiMcfgInfo { void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info, const char *oem_id, const char *oem_table_id); -Aml *aml_pci_device_dsm(void); -void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus); void build_pci_bridge_aml(AcpiDevAmlIf *adev, Aml *scope); void build_srat_generic_affinity_structures(GArray *table_data); +Aml *build_pci_host_bridge_osc_method(bool enable_native_pcie_hotplug); +Aml *build_pci_bridge_edsm(void); + #endif diff --git a/include/hw/acpi/pcihp.h b/include/hw/acpi/pcihp.h index a97904b..ca6a258 100644 --- a/include/hw/acpi/pcihp.h +++ b/include/hw/acpi/pcihp.h @@ -3,7 +3,7 @@ * * QEMU supports PCI hotplug via ACPI. This module * implements the interface between QEMU and the ACPI BIOS. - * Interface specification - see docs/specs/acpi_pci_hotplug.txt + * Interface specification - see docs/specs/acpi_pci_hotplug.rst * * Copyright (c) 2013, Red Hat Inc, Michael S. Tsirkin (mst@redhat.com) * Copyright (c) 2006 Fabrice Bellard @@ -28,11 +28,18 @@ #define HW_ACPI_PCIHP_H #include "hw/acpi/acpi.h" +#include "hw/acpi/aml-build.h" #include "hw/hotplug.h" #define ACPI_PCIHP_IO_BASE_PROP "acpi-pcihp-io-base" #define ACPI_PCIHP_IO_LEN_PROP "acpi-pcihp-io-len" +/* PCI Hot-plug registers bases. See docs/specs/acpi_pci_hotplug.rst */ +#define ACPI_PCIHP_SEJ_BASE 0x8 +#define ACPI_PCIHP_BNMR_BASE 0x10 + +#define ACPI_PCIHP_SIZE 0x0018 + typedef struct AcpiPciHpPciStatus { uint32_t up; uint32_t down; @@ -55,7 +62,7 @@ typedef struct AcpiPciHpState { bool use_acpi_root_pci_hotplug; } AcpiPciHpState; -void acpi_pcihp_init(Object *owner, AcpiPciHpState *, PCIBus *root, +void acpi_pcihp_init(Object *owner, AcpiPciHpState *, MemoryRegion *io, uint16_t io_base); bool acpi_pcihp_is_hotpluggable_bus(AcpiPciHpState *s, BusState *bus); @@ -69,6 +76,14 @@ void acpi_pcihp_device_unplug_request_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s, DeviceState *dev, Error **errp); +void build_acpi_pci_hotplug(Aml *table, AmlRegionSpace rs, uint64_t pcihp_addr); +void build_append_pci_dsm_func0_common(Aml *ctx, Aml *retvar); +void build_append_pcihp_resources(Aml *table, + uint64_t io_addr, uint64_t io_len); +bool build_append_notification_callback(Aml *parent_scope, const PCIBus *bus); + +void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus); + /* Called on reset */ void acpi_pcihp_reset(AcpiPciHpState *s); diff --git a/include/hw/arm/aspeed.h b/include/hw/arm/aspeed.h index 973277b..714bbd3 100644 --- a/include/hw/arm/aspeed.h +++ b/include/hw/arm/aspeed.h @@ -11,6 +11,7 @@ #include "hw/boards.h" #include "qom/object.h" +#include "hw/arm/aspeed_soc.h" typedef struct AspeedMachineState AspeedMachineState; @@ -24,6 +25,24 @@ DECLARE_OBJ_CHECKERS(AspeedMachineState, AspeedMachineClass, #define ASPEED_MAC2_ON (1 << 2) #define ASPEED_MAC3_ON (1 << 3) +/* On 32-bit hosts, lower RAM to 1G because of the 2047 MB limit */ +#if HOST_LONG_BITS == 32 +#define ASPEED_RAM_SIZE(sz) MIN((sz), 1 * GiB) +#else +#define ASPEED_RAM_SIZE(sz) (sz) +#endif + +struct AspeedMachineState { + MachineState parent_obj; + + AspeedSoCState *soc; + MemoryRegion boot_rom; + bool mmio_exec; + uint32_t uart_chosen; + char *fmc_model; + char *spi_model; + uint32_t hw_strap1; +}; struct AspeedMachineClass { MachineClass parent_obj; @@ -35,7 +54,9 @@ struct AspeedMachineClass { uint32_t hw_strap2; const char *fmc_model; const char *spi_model; + const char *spi2_model; uint32_t num_cs; + uint32_t num_cs2; uint32_t macs_mask; void (*i2c_init)(AspeedMachineState *bmc); uint32_t uart_default; @@ -43,5 +64,65 @@ struct AspeedMachineClass { bool vbootrom; }; +/* + * aspeed_machine_class_init_cpus_defaults: + * @mc: the #MachineClass to be initialized. + * + * Initialize the default CPU configuration for an Aspeed machine class. + * This function sets the default, minimum, and maximum CPU counts + * to match the number of CPUs defined in the associated SoC class, + * and copies its list of valid CPU types. + */ +void aspeed_machine_class_init_cpus_defaults(MachineClass *mc); + +/* + * aspeed_create_pca9552: + * @soc: pointer to the #AspeedSoCState. + * @bus_id: the I2C bus index to attach the device. + * @addr: the I2C address of the PCA9552 device. + * + * Create and attach a PCA9552 LED controller device to the specified I2C bus + * of the given Aspeed SoC. The device is instantiated using + * i2c_slave_create_simple() with the PCA9552 device type. + */ +void aspeed_create_pca9552(AspeedSoCState *soc, int bus_id, int addr); + +/* + * aspeed_create_pca9554: + * @soc: pointer to the #AspeedSoCState. + * @bus_id: the I2C bus index to attach the device. + * @addr: the I2C address of the PCA9554 device. + * + * Create and attach a PCA9554 I/O expander to the specified I2C bus + * of the given Aspeed SoC. The device is created via + * i2c_slave_create_simple() and returned as an #I2CSlave pointer. + * + * Returns: a pointer to the newly created #I2CSlave instance. + */ +I2CSlave *aspeed_create_pca9554(AspeedSoCState *soc, int bus_id, int addr); + +/* + * aspeed_machine_ast2600_class_emmc_init: + * @oc: the #ObjectClass to initialize. + * + * Initialize eMMC-related properties for the AST2600 Aspeed machine class. + * This function is typically invoked during class initialization to set up + * default configuration or attach eMMC-specific devices for AST2600 platforms. + */ +void aspeed_machine_ast2600_class_emmc_init(ObjectClass *oc); + +/* + * aspeed_connect_serial_hds_to_uarts: + * @bmc: pointer to the #AspeedMachineState. + * + * Connect host serial backends (character devices) to the UART interfaces + * of the Aspeed SoC used by the given BMC machine. + * + * The function assigns `serial_hd(0)` to the primary UART channel + * (either chosen via `bmc->uart_chosen` or the machine class default), + * and iteratively connects remaining serial ports to other available UARTs + * on the SoC based on their index. + */ +void aspeed_connect_serial_hds_to_uarts(AspeedMachineState *bmc); #endif diff --git a/include/hw/arm/aspeed_coprocessor.h b/include/hw/arm/aspeed_coprocessor.h new file mode 100644 index 0000000..4a50f68 --- /dev/null +++ b/include/hw/arm/aspeed_coprocessor.h @@ -0,0 +1,63 @@ +/* + * ASPEED Coprocessor + * + * Copyright (C) 2025 ASPEED Technology Inc. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef ASPEED_COPROCESSOR_H +#define ASPEED_COPROCESSOR_H + +#include "qom/object.h" +#include "hw/arm/aspeed_soc.h" + +struct AspeedCoprocessorState { + DeviceState parent; + + MemoryRegion *memory; + MemoryRegion sdram; + MemoryRegion *sram; + MemoryRegion sram_alias; + MemoryRegion uart_alias; + MemoryRegion scu_alias; + Clock *sysclk; + + AspeedSCUState *scu; + AspeedSCUState scuio; + AspeedTimerCtrlState timerctrl; + SerialMM *uart; + int uart_dev; +}; + +#define TYPE_ASPEED_COPROCESSOR "aspeed-coprocessor" +OBJECT_DECLARE_TYPE(AspeedCoprocessorState, AspeedCoprocessorClass, + ASPEED_COPROCESSOR) + +struct AspeedCoprocessorClass { + DeviceClass parent_class; + + /** valid_cpu_types: NULL terminated array of a single CPU type. */ + const char * const *valid_cpu_types; + const hwaddr *memmap; + const int *irqmap; +}; + +struct Aspeed27x0CoprocessorState { + AspeedCoprocessorState parent; + AspeedINTCState intc[2]; + UnimplementedDeviceState ipc[2]; + UnimplementedDeviceState scuio; + + ARMv7MState armv7m; +}; + +#define TYPE_ASPEED27X0SSP_COPROCESSOR "aspeed27x0ssp-coprocessor" +OBJECT_DECLARE_SIMPLE_TYPE(Aspeed27x0CoprocessorState, + ASPEED27X0SSP_COPROCESSOR) + +#define TYPE_ASPEED27X0TSP_COPROCESSOR "aspeed27x0tsp-coprocessor" +DECLARE_OBJ_CHECKERS(Aspeed27x0CoprocessorState, AspeedCoprocessorClass, + ASPEED27X0TSP_COPROCESSOR, TYPE_ASPEED27X0TSP_COPROCESSOR) + +#endif /* ASPEED_COPROCESSOR_H */ diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index 217ef0e..4b8e599 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -37,11 +37,14 @@ #include "qom/object.h" #include "hw/misc/aspeed_lpc.h" #include "hw/misc/unimp.h" +#include "hw/pci-host/aspeed_pcie.h" #include "hw/misc/aspeed_peci.h" #include "hw/fsi/aspeed_apb2opb.h" #include "hw/char/serial-mm.h" #include "hw/intc/arm_gicv3.h" +#define VBOOTROM_FILE_NAME "ast27x0_bootrom.bin" + #define ASPEED_SPIS_NUM 3 #define ASPEED_EHCIS_NUM 4 #define ASPEED_WDTS_NUM 8 @@ -49,6 +52,7 @@ #define ASPEED_MACS_NUM 4 #define ASPEED_UARTS_NUM 13 #define ASPEED_JTAG_NUM 2 +#define ASPEED_PCIE_NUM 3 struct AspeedSoCState { DeviceState parent; @@ -60,6 +64,7 @@ struct AspeedSoCState { MemoryRegion spi_boot_container; MemoryRegion spi_boot; MemoryRegion vbootrom; + MemoryRegion pcie_mmio_alias[ASPEED_PCIE_NUM]; AddressSpace dram_as; AspeedRtcState rtc; AspeedTimerCtrlState timerctrl; @@ -87,6 +92,8 @@ struct AspeedSoCState { AspeedSDHCIState sdhci; AspeedSDHCIState emmc; AspeedLPCState lpc; + AspeedPCIECfgState pcie[ASPEED_PCIE_NUM]; + AspeedPCIEPhyState pcie_phy[ASPEED_PCIE_NUM]; AspeedPECIState peci; SerialMM uart[ASPEED_UARTS_NUM]; Clock *sysclk; @@ -146,30 +153,6 @@ struct Aspeed10x0SoCState { ARMv7MState armv7m; }; -struct Aspeed27x0SSPSoCState { - AspeedSoCState parent; - AspeedINTCState intc[2]; - UnimplementedDeviceState ipc[2]; - UnimplementedDeviceState scuio; - - ARMv7MState armv7m; -}; - -#define TYPE_ASPEED27X0SSP_SOC "aspeed27x0ssp-soc" -OBJECT_DECLARE_SIMPLE_TYPE(Aspeed27x0SSPSoCState, ASPEED27X0SSP_SOC) - -struct Aspeed27x0TSPSoCState { - AspeedSoCState parent; - AspeedINTCState intc[2]; - UnimplementedDeviceState ipc[2]; - UnimplementedDeviceState scuio; - - ARMv7MState armv7m; -}; - -#define TYPE_ASPEED27X0TSP_SOC "aspeed27x0tsp-soc" -OBJECT_DECLARE_SIMPLE_TYPE(Aspeed27x0TSPSoCState, ASPEED27X0TSP_SOC) - #define TYPE_ASPEED10X0_SOC "aspeed10x0-soc" OBJECT_DECLARE_SIMPLE_TYPE(Aspeed10x0SoCState, ASPEED10X0_SOC) @@ -181,6 +164,7 @@ struct AspeedSoCClass { uint32_t silicon_rev; uint64_t sram_size; uint64_t secsram_size; + int pcie_num; int spis_num; int ehcis_num; int wdts_num; @@ -190,12 +174,9 @@ struct AspeedSoCClass { const int *irqmap; const hwaddr *memmap; uint32_t num_cpus; - qemu_irq (*get_irq)(AspeedSoCState *s, int dev); bool (*boot_from_emmc)(AspeedSoCState *s); }; -const char *aspeed_soc_cpu_type(AspeedSoCClass *sc); - enum { ASPEED_DEV_VBOOTROM, ASPEED_DEV_SPI_BOOT, @@ -254,6 +235,15 @@ enum { ASPEED_DEV_LPC, ASPEED_DEV_IBT, ASPEED_DEV_I2C, + ASPEED_DEV_PCIE0, + ASPEED_DEV_PCIE1, + ASPEED_DEV_PCIE2, + ASPEED_DEV_PCIE_PHY0, + ASPEED_DEV_PCIE_PHY1, + ASPEED_DEV_PCIE_PHY2, + ASPEED_DEV_PCIE_MMIO0, + ASPEED_DEV_PCIE_MMIO1, + ASPEED_DEV_PCIE_MMIO2, ASPEED_DEV_PECI, ASPEED_DEV_ETH1, ASPEED_DEV_ETH2, @@ -287,30 +277,39 @@ enum { ASPEED_DEV_IPC1, }; -qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev); -bool aspeed_soc_uart_realize(AspeedSoCState *s, Error **errp); -void aspeed_soc_uart_set_chr(AspeedSoCState *s, int dev, Chardev *chr); +const char *aspeed_soc_cpu_type(const char * const *valid_cpu_types); +bool aspeed_soc_uart_realize(MemoryRegion *memory, SerialMM *smm, + const hwaddr addr, Error **errp); +void aspeed_soc_uart_set_chr(SerialMM *uart, int dev, int uarts_base, + int uarts_num, Chardev *chr); bool aspeed_soc_dram_init(AspeedSoCState *s, Error **errp); -void aspeed_mmio_map(AspeedSoCState *s, SysBusDevice *dev, int n, hwaddr addr); -void aspeed_mmio_map_unimplemented(AspeedSoCState *s, SysBusDevice *dev, +void aspeed_mmio_map(MemoryRegion *memory, SysBusDevice *dev, int n, + hwaddr addr); +void aspeed_mmio_map_unimplemented(MemoryRegion *memory, SysBusDevice *dev, const char *name, hwaddr addr, uint64_t size); void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype, unsigned int count, int unit0); +void aspeed_write_boot_rom(BlockBackend *blk, hwaddr addr, size_t rom_size, + Error **errp); +void aspeed_install_boot_rom(AspeedSoCState *soc, BlockBackend *blk, + MemoryRegion *boot_rom, uint64_t rom_size); +void aspeed_load_vbootrom(AspeedSoCState *soc, const char *bios_name, + Error **errp); static inline int aspeed_uart_index(int uart_dev) { return uart_dev - ASPEED_DEV_UART0; } -static inline int aspeed_uart_first(AspeedSoCClass *sc) +static inline int aspeed_uart_first(int uarts_base) { - return aspeed_uart_index(sc->uarts_base); + return aspeed_uart_index(uarts_base); } -static inline int aspeed_uart_last(AspeedSoCClass *sc) +static inline int aspeed_uart_last(int uarts_base, int uarts_num) { - return aspeed_uart_first(sc) + sc->uarts_num - 1; + return aspeed_uart_first(uarts_base) + uarts_num - 1; } #endif /* ASPEED_SOC_H */ diff --git a/include/hw/arm/boot.h b/include/hw/arm/boot.h index b12bf61..a2e22bd 100644 --- a/include/hw/arm/boot.h +++ b/include/hw/arm/boot.h @@ -132,6 +132,9 @@ struct arm_boot_info { bool secure_board_setup; arm_endianness endianness; + + /* CPU having load the kernel and that should be the first to boot. */ + ARMCPU *primary_cpu; }; /** diff --git a/include/hw/arm/machines-qom.h b/include/hw/arm/machines-qom.h new file mode 100644 index 0000000..3f64d5e --- /dev/null +++ b/include/hw/arm/machines-qom.h @@ -0,0 +1,46 @@ +/* + * QOM type definitions for ARM / Aarch64 machines + * + * Copyright (c) Linaro + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_ARM_MACHINES_QOM_H +#define HW_ARM_MACHINES_QOM_H + +#include "hw/boards.h" + +#define TYPE_TARGET_ARM_MACHINE \ + "target-info-arm-machine" + +#define TYPE_TARGET_AARCH64_MACHINE \ + "target-info-aarch64-machine" + +/* + * A machine filtered with arm_machine_interfaces[] or + * arm_aarch64_machine_interfaces[] will be available + * in both qemu-system-arm and qemu-system-aarch64 binaries. + * + * One filtered with aarch64_machine_interfaces[] will only + * be available in the qemu-system-aarch64 binary. + */ +extern const InterfaceInfo arm_machine_interfaces[]; +extern const InterfaceInfo arm_aarch64_machine_interfaces[]; +extern const InterfaceInfo aarch64_machine_interfaces[]; + +/* + * A machine defined with the DEFINE_MACHINE_ARM() macro will be + * available in both qemu-system-arm and qemu-system-aarch64 binaries. + * + * One defined with DEFINE_MACHINE_AARCH64() will only be available in + * the qemu-system-aarch64 binary. + */ +#define DEFINE_MACHINE_ARM(namestr, machine_initfn) \ + DEFINE_MACHINE_WITH_INTERFACE_ARRAY(namestr, machine_initfn, \ + arm_machine_interfaces) +#define DEFINE_MACHINE_AARCH64(namestr, machine_initfn) \ + DEFINE_MACHINE_WITH_INTERFACE_ARRAY(namestr, machine_initfn, \ + aarch64_machine_interfaces) + +#endif diff --git a/include/hw/arm/max78000_soc.h b/include/hw/arm/max78000_soc.h new file mode 100644 index 0000000..a203079 --- /dev/null +++ b/include/hw/arm/max78000_soc.h @@ -0,0 +1,50 @@ +/* + * MAX78000 SOC + * + * Copyright (c) 2025 Jackson Donaldson <jcksn@duck.com> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_ARM_MAX78000_SOC_H +#define HW_ARM_MAX78000_SOC_H + +#include "hw/or-irq.h" +#include "hw/arm/armv7m.h" +#include "hw/misc/max78000_aes.h" +#include "hw/misc/max78000_gcr.h" +#include "hw/misc/max78000_icc.h" +#include "hw/char/max78000_uart.h" +#include "hw/misc/max78000_trng.h" +#include "qom/object.h" + +#define TYPE_MAX78000_SOC "max78000-soc" +OBJECT_DECLARE_SIMPLE_TYPE(MAX78000State, MAX78000_SOC) + +#define FLASH_BASE_ADDRESS 0x10000000 +#define FLASH_SIZE (512 * 1024) +#define SRAM_BASE_ADDRESS 0x20000000 +#define SRAM_SIZE (128 * 1024) + +/* The MAX78k has 2 instruction caches; only icc0 matters, icc1 is for RISC */ +#define MAX78000_NUM_ICC 2 +#define MAX78000_NUM_UART 3 + +struct MAX78000State { + SysBusDevice parent_obj; + + ARMv7MState armv7m; + + MemoryRegion sram; + MemoryRegion flash; + + Max78000GcrState gcr; + Max78000IccState icc[MAX78000_NUM_ICC]; + Max78000UartState uart[MAX78000_NUM_UART]; + Max78000TrngState trng; + Max78000AesState aes; + + Clock *sysclk; +}; + +#endif diff --git a/include/hw/arm/npcm8xx.h b/include/hw/arm/npcm8xx.h index 3436abf..a8377db 100644 --- a/include/hw/arm/npcm8xx.h +++ b/include/hw/arm/npcm8xx.h @@ -28,7 +28,8 @@ #include "hw/misc/npcm7xx_mft.h" #include "hw/misc/npcm7xx_pwm.h" #include "hw/misc/npcm7xx_rng.h" -#include "hw/net/npcm7xx_emc.h" +#include "hw/net/npcm_gmac.h" +#include "hw/net/npcm_pcs.h" #include "hw/nvram/npcm7xx_otp.h" #include "hw/sd/npcm7xx_sdhci.h" #include "hw/timer/npcm7xx_timer.h" @@ -99,6 +100,8 @@ struct NPCM8xxState { EHCISysBusState ehci[2]; OHCISysBusState ohci[2]; NPCM7xxFIUState fiu[3]; + NPCMGMACState gmac[4]; + NPCMPCSState pcs; NPCM7xxSDHCIState mmc; NPCMPSPIState pspi; }; diff --git a/include/hw/arm/sharpsl.h b/include/hw/arm/sharpsl.h deleted file mode 100644 index 1e3992f..0000000 --- a/include/hw/arm/sharpsl.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Common declarations for the Zaurii. - * - * This file is licensed under the GNU GPL. - */ - -#ifndef QEMU_SHARPSL_H -#define QEMU_SHARPSL_H - -#include "exec/hwaddr.h" - -/* zaurus.c */ - -#define SL_PXA_PARAM_BASE 0xa0000a00 -void sl_bootparam_write(hwaddr ptr); - -#endif diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h index e5e2d09..80d0fec 100644 --- a/include/hw/arm/smmu-common.h +++ b/include/hw/arm/smmu-common.h @@ -161,6 +161,7 @@ struct SMMUState { QLIST_HEAD(, SMMUDevice) devices_with_notifiers; uint8_t bus_num; PCIBus *primary_bus; + bool smmu_per_bus; /* SMMU is specific to the primary_bus */ }; struct SMMUBaseClass { diff --git a/include/hw/arm/stm32f205_soc.h b/include/hw/arm/stm32f205_soc.h index 4f4c8bb..46eda34 100644 --- a/include/hw/arm/stm32f205_soc.h +++ b/include/hw/arm/stm32f205_soc.h @@ -59,7 +59,7 @@ struct STM32F205State { STM32F2XXADCState adc[STM_NUM_ADCS]; STM32F2XXSPIState spi[STM_NUM_SPIS]; - OrIRQState *adc_irqs; + OrIRQState adc_irqs; MemoryRegion sram; MemoryRegion flash; diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index 9a1b0f5..c77a33f 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -33,9 +33,11 @@ #include "exec/hwaddr.h" #include "qemu/notify.h" #include "hw/boards.h" +#include "hw/acpi/ghes.h" #include "hw/arm/boot.h" #include "hw/arm/bsa.h" #include "hw/block/flash.h" +#include "hw/cxl/cxl.h" #include "system/kvm.h" #include "hw/intc/arm_gicv3_common.h" #include "qom/object.h" @@ -79,12 +81,14 @@ enum { VIRT_ACPI_GED, VIRT_NVDIMM_ACPI, VIRT_PVTIME, + VIRT_ACPI_PCIHP, VIRT_LOWMEMMAP_LAST, }; /* indices of IO regions located after the RAM */ enum { VIRT_HIGH_GIC_REDIST2 = VIRT_LOWMEMMAP_LAST, + VIRT_CXL_HOST, VIRT_HIGH_PCIE_ECAM, VIRT_HIGH_PCIE_MMIO, }; @@ -119,8 +123,6 @@ struct VirtMachineClass { MachineClass parent; bool no_tcg_its; bool no_highmem_compact; - bool no_ged; /* Machines < 4.2 have no support for ACPI GED device */ - bool kvm_no_adjvtime; bool no_kvm_steal_time; bool acpi_expose_flash; bool no_secure_gpio; @@ -140,6 +142,7 @@ struct VirtMachineState { bool secure; bool highmem; bool highmem_compact; + bool highmem_cxl; bool highmem_ecam; bool highmem_mmio; bool highmem_redists; @@ -170,10 +173,13 @@ struct VirtMachineState { DeviceState *gic; DeviceState *acpi_dev; Notifier powerdown_notifier; + Notifier generic_error_notifier; PCIBus *bus; char *oem_id; char *oem_table_id; bool ns_el2_virt_timer_irq; + CXLState cxl_devices_state; + bool legacy_smmuv3_present; }; #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM) diff --git a/include/hw/arm/xen_arch_hvm.h b/include/hw/arm/xen_arch_hvm.h deleted file mode 100644 index 8fd645e..0000000 --- a/include/hw/arm/xen_arch_hvm.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef HW_XEN_ARCH_ARM_HVM_H -#define HW_XEN_ARCH_ARM_HVM_H - -#include <xen/hvm/ioreq.h> -void arch_handle_ioreq(XenIOState *state, ioreq_t *req); -void arch_xen_set_memory(XenIOState *state, - MemoryRegionSection *section, - bool add); -#endif diff --git a/include/hw/arm/xlnx-versal-version.h b/include/hw/arm/xlnx-versal-version.h new file mode 100644 index 0000000..5b6b6e5 --- /dev/null +++ b/include/hw/arm/xlnx-versal-version.h @@ -0,0 +1,16 @@ +/* + * AMD Versal versions + * + * Copyright (c) 2025 Advanced Micro Devices, Inc. + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_ARM_XLNX_VERSAL_VERSION_H +#define HW_ARM_XLNX_VERSAL_VERSION_H + +typedef enum VersalVersion { + VERSAL_VER_VERSAL, + VERSAL_VER_VERSAL2, +} VersalVersion; + +#endif diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index 05ed641..e1fb1f4 100644 --- a/include/hw/arm/xlnx-versal.h +++ b/include/hw/arm/xlnx-versal.h @@ -1,7 +1,8 @@ /* - * Model of the Xilinx Versal + * AMD/Xilinx Versal family SoC model. * * Copyright (c) 2018 Xilinx Inc. + * Copyright (c) 2025 Advanced Micro Devices, Inc. * Written by Edgar E. Iglesias * * This program is free software; you can redistribute it and/or modify @@ -13,326 +14,77 @@ #define XLNX_VERSAL_H #include "hw/sysbus.h" -#include "hw/cpu/cluster.h" -#include "hw/or-irq.h" -#include "hw/sd/sdhci.h" -#include "hw/intc/arm_gicv3.h" -#include "hw/char/pl011.h" -#include "hw/dma/xlnx-zdma.h" -#include "hw/net/cadence_gem.h" -#include "hw/rtc/xlnx-zynqmp-rtc.h" #include "qom/object.h" -#include "hw/usb/xlnx-usb-subsystem.h" -#include "hw/misc/xlnx-versal-xramc.h" -#include "hw/nvram/xlnx-bbram.h" -#include "hw/nvram/xlnx-versal-efuse.h" -#include "hw/ssi/xlnx-versal-ospi.h" -#include "hw/dma/xlnx_csu_dma.h" -#include "hw/misc/xlnx-versal-crl.h" -#include "hw/misc/xlnx-versal-pmc-iou-slcr.h" -#include "hw/misc/xlnx-versal-trng.h" -#include "hw/net/xlnx-versal-canfd.h" -#include "hw/misc/xlnx-versal-cfu.h" -#include "hw/misc/xlnx-versal-cframe-reg.h" -#include "target/arm/cpu.h" +#include "net/can_emu.h" +#include "hw/arm/xlnx-versal-version.h" -#define TYPE_XLNX_VERSAL "xlnx-versal" -OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL) +#define TYPE_XLNX_VERSAL_BASE "xlnx-versal-base" +OBJECT_DECLARE_TYPE(Versal, VersalClass, XLNX_VERSAL_BASE) -#define XLNX_VERSAL_NR_ACPUS 2 -#define XLNX_VERSAL_NR_RCPUS 2 -#define XLNX_VERSAL_NR_UARTS 2 -#define XLNX_VERSAL_NR_GEMS 2 -#define XLNX_VERSAL_NR_ADMAS 8 -#define XLNX_VERSAL_NR_SDS 2 -#define XLNX_VERSAL_NR_XRAM 4 -#define XLNX_VERSAL_NR_IRQS 192 -#define XLNX_VERSAL_NR_CANFD 2 -#define XLNX_VERSAL_CANFD_REF_CLK (24 * 1000 * 1000) -#define XLNX_VERSAL_NR_CFRAME 15 +#define TYPE_XLNX_VERSAL "xlnx-versal" +#define TYPE_XLNX_VERSAL2 "xlnx-versal2" struct Versal { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ - struct { - struct { - MemoryRegion mr; - CPUClusterState cluster; - ARMCPU cpu[XLNX_VERSAL_NR_ACPUS]; - GICv3State gic; - } apu; - } fpd; - + GArray *intc; MemoryRegion mr_ps; struct { - /* 4 ranges to access DDR. */ - MemoryRegion mr_ddr_ranges[4]; - } noc; - - struct { - MemoryRegion mr_ocm; - - struct { - PL011State uart[XLNX_VERSAL_NR_UARTS]; - CadenceGEMState gem[XLNX_VERSAL_NR_GEMS]; - OrIRQState gem_irq_orgate[XLNX_VERSAL_NR_GEMS]; - XlnxZDMA adma[XLNX_VERSAL_NR_ADMAS]; - VersalUsb2 usb; - CanBusState *canbus[XLNX_VERSAL_NR_CANFD]; - XlnxVersalCANFDState canfd[XLNX_VERSAL_NR_CANFD]; - } iou; - - /* Real-time Processing Unit. */ - struct { - MemoryRegion mr; - MemoryRegion mr_ps_alias; - - CPUClusterState cluster; - ARMCPU cpu[XLNX_VERSAL_NR_RCPUS]; - } rpu; - - struct { - OrIRQState irq_orgate; - XlnxXramCtrl ctrl[XLNX_VERSAL_NR_XRAM]; - } xram; - - XlnxVersalCRL crl; - } lpd; - - /* The Platform Management Controller subsystem. */ - struct { - struct { - SDHCIState sd[XLNX_VERSAL_NR_SDS]; - XlnxVersalPmcIouSlcr slcr; - - struct { - XlnxVersalOspi ospi; - XlnxCSUDMA dma_src; - XlnxCSUDMA dma_dst; - MemoryRegion linear_mr; - OrIRQState irq_orgate; - } ospi; - } iou; - - XlnxZynqMPRTC rtc; - XlnxVersalTRng trng; - XlnxBBRam bbram; - XlnxEFuse efuse; - XlnxVersalEFuseCtrl efuse_ctrl; - XlnxVersalEFuseCache efuse_cache; - XlnxVersalCFUAPB cfu_apb; - XlnxVersalCFUFDRO cfu_fdro; - XlnxVersalCFUSFR cfu_sfr; - XlnxVersalCFrameReg cframe[XLNX_VERSAL_NR_CFRAME]; - XlnxVersalCFrameBcastReg cframe_bcast; - - OrIRQState apb_irq_orgate; - } pmc; + uint32_t clk_25mhz; + uint32_t clk_125mhz; + uint32_t gic; + } phandle; struct { MemoryRegion *mr_ddr; + CanBusState **canbus; + void *fdt; } cfg; }; -/* Memory-map and IRQ definitions. Copied a subset from - * auto-generated files. */ - -#define VERSAL_GIC_MAINT_IRQ 9 -#define VERSAL_TIMER_VIRT_IRQ 11 -#define VERSAL_TIMER_S_EL1_IRQ 13 -#define VERSAL_TIMER_NS_EL1_IRQ 14 -#define VERSAL_TIMER_NS_EL2_IRQ 10 - -#define VERSAL_CRL_IRQ 10 -#define VERSAL_UART0_IRQ_0 18 -#define VERSAL_UART1_IRQ_0 19 -#define VERSAL_CANFD0_IRQ_0 20 -#define VERSAL_CANFD1_IRQ_0 21 -#define VERSAL_USB0_IRQ_0 22 -#define VERSAL_GEM0_IRQ_0 56 -#define VERSAL_GEM0_WAKE_IRQ_0 57 -#define VERSAL_GEM1_IRQ_0 58 -#define VERSAL_GEM1_WAKE_IRQ_0 59 -#define VERSAL_ADMA_IRQ_0 60 -#define VERSAL_XRAM_IRQ_0 79 -#define VERSAL_CFU_IRQ_0 120 -#define VERSAL_PMC_APB_IRQ 121 -#define VERSAL_OSPI_IRQ 124 -#define VERSAL_SD0_IRQ_0 126 -#define VERSAL_EFUSE_IRQ 139 -#define VERSAL_TRNG_IRQ 141 -#define VERSAL_RTC_ALARM_IRQ 142 -#define VERSAL_RTC_SECONDS_IRQ 143 - -/* Architecturally reserved IRQs suitable for virtualization. */ -#define VERSAL_RSVD_IRQ_FIRST 111 -#define VERSAL_RSVD_IRQ_LAST 118 - -#define MM_TOP_RSVD 0xa0000000U -#define MM_TOP_RSVD_SIZE 0x4000000 -#define MM_GIC_APU_DIST_MAIN 0xf9000000U -#define MM_GIC_APU_DIST_MAIN_SIZE 0x10000 -#define MM_GIC_APU_REDIST_0 0xf9080000U -#define MM_GIC_APU_REDIST_0_SIZE 0x80000 - -#define MM_UART0 0xff000000U -#define MM_UART0_SIZE 0x10000 -#define MM_UART1 0xff010000U -#define MM_UART1_SIZE 0x10000 - -#define MM_CANFD0 0xff060000U -#define MM_CANFD0_SIZE 0x10000 -#define MM_CANFD1 0xff070000U -#define MM_CANFD1_SIZE 0x10000 - -#define MM_GEM0 0xff0c0000U -#define MM_GEM0_SIZE 0x10000 -#define MM_GEM1 0xff0d0000U -#define MM_GEM1_SIZE 0x10000 +struct VersalClass { + SysBusDeviceClass parent; -#define MM_ADMA_CH0 0xffa80000U -#define MM_ADMA_CH0_SIZE 0x10000 - -#define MM_OCM 0xfffc0000U -#define MM_OCM_SIZE 0x40000 - -#define MM_XRAM 0xfe800000 -#define MM_XRAMC 0xff8e0000 -#define MM_XRAMC_SIZE 0x10000 - -#define MM_USB2_CTRL_REGS 0xFF9D0000 -#define MM_USB2_CTRL_REGS_SIZE 0x10000 - -#define MM_USB_0 0xFE200000 -#define MM_USB_0_SIZE 0x10000 - -#define MM_TOP_DDR 0x0 -#define MM_TOP_DDR_SIZE 0x80000000U -#define MM_TOP_DDR_2 0x800000000ULL -#define MM_TOP_DDR_2_SIZE 0x800000000ULL -#define MM_TOP_DDR_3 0xc000000000ULL -#define MM_TOP_DDR_3_SIZE 0x4000000000ULL -#define MM_TOP_DDR_4 0x10000000000ULL -#define MM_TOP_DDR_4_SIZE 0xb780000000ULL - -#define MM_PSM_START 0xffc80000U -#define MM_PSM_END 0xffcf0000U + VersalVersion version; +}; -#define MM_CRL 0xff5e0000U -#define MM_CRL_SIZE 0x300000 -#define MM_IOU_SCNTR 0xff130000U -#define MM_IOU_SCNTR_SIZE 0x10000 -#define MM_IOU_SCNTRS 0xff140000U -#define MM_IOU_SCNTRS_SIZE 0x10000 -#define MM_FPD_CRF 0xfd1a0000U -#define MM_FPD_CRF_SIZE 0x140000 -#define MM_FPD_FPD_APU 0xfd5c0000 -#define MM_FPD_FPD_APU_SIZE 0x100 +static inline void versal_set_fdt(Versal *s, void *fdt) +{ + g_assert(!qdev_is_realized(DEVICE(s))); + s->cfg.fdt = fdt; +} -#define MM_PMC_PMC_IOU_SLCR 0xf1060000 -#define MM_PMC_PMC_IOU_SLCR_SIZE 0x10000 +void versal_fdt_add_memory_nodes(Versal *s, uint64_t ram_size); -#define MM_PMC_OSPI 0xf1010000 -#define MM_PMC_OSPI_SIZE 0x10000 +DeviceState *versal_get_boot_cpu(Versal *s); +void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk); +void versal_efuse_attach_drive(Versal *s, BlockBackend *blk); +void versal_bbram_attach_drive(Versal *s, BlockBackend *blk); +void versal_ospi_create_flash(Versal *s, int flash_idx, const char *flash_mdl, + BlockBackend *blk); -#define MM_PMC_OSPI_DAC 0xc0000000 -#define MM_PMC_OSPI_DAC_SIZE 0x20000000 +qemu_irq versal_get_reserved_irq(Versal *s, int idx, int *dtb_idx); +hwaddr versal_get_reserved_mmio_addr(Versal *s); -#define MM_PMC_OSPI_DMA_DST 0xf1011800 -#define MM_PMC_OSPI_DMA_SRC 0xf1011000 +int versal_get_num_cpu(VersalVersion version); +int versal_get_num_can(VersalVersion version); +int versal_get_num_sdhci(VersalVersion version); -#define MM_PMC_SD0 0xf1040000U -#define MM_PMC_SD0_SIZE 0x10000 -#define MM_PMC_BBRAM_CTRL 0xf11f0000 -#define MM_PMC_BBRAM_CTRL_SIZE 0x00050 -#define MM_PMC_EFUSE_CTRL 0xf1240000 -#define MM_PMC_EFUSE_CTRL_SIZE 0x00104 -#define MM_PMC_EFUSE_CACHE 0xf1250000 -#define MM_PMC_EFUSE_CACHE_SIZE 0x00C00 +static inline const char *versal_get_class(VersalVersion version) +{ + switch (version) { + case VERSAL_VER_VERSAL: + return TYPE_XLNX_VERSAL; -#define MM_PMC_CFU_APB 0xf12b0000 -#define MM_PMC_CFU_APB_SIZE 0x10000 -#define MM_PMC_CFU_STREAM 0xf12c0000 -#define MM_PMC_CFU_STREAM_SIZE 0x1000 -#define MM_PMC_CFU_SFR 0xf12c1000 -#define MM_PMC_CFU_SFR_SIZE 0x1000 -#define MM_PMC_CFU_FDRO 0xf12c2000 -#define MM_PMC_CFU_FDRO_SIZE 0x1000 -#define MM_PMC_CFU_STREAM_2 0xf1f80000 -#define MM_PMC_CFU_STREAM_2_SIZE 0x40000 + case VERSAL_VER_VERSAL2: + return TYPE_XLNX_VERSAL2; -#define MM_PMC_CFRAME0_REG 0xf12d0000 -#define MM_PMC_CFRAME0_REG_SIZE 0x1000 -#define MM_PMC_CFRAME0_FDRI 0xf12d1000 -#define MM_PMC_CFRAME0_FDRI_SIZE 0x1000 -#define MM_PMC_CFRAME1_REG 0xf12d2000 -#define MM_PMC_CFRAME1_REG_SIZE 0x1000 -#define MM_PMC_CFRAME1_FDRI 0xf12d3000 -#define MM_PMC_CFRAME1_FDRI_SIZE 0x1000 -#define MM_PMC_CFRAME2_REG 0xf12d4000 -#define MM_PMC_CFRAME2_REG_SIZE 0x1000 -#define MM_PMC_CFRAME2_FDRI 0xf12d5000 -#define MM_PMC_CFRAME2_FDRI_SIZE 0x1000 -#define MM_PMC_CFRAME3_REG 0xf12d6000 -#define MM_PMC_CFRAME3_REG_SIZE 0x1000 -#define MM_PMC_CFRAME3_FDRI 0xf12d7000 -#define MM_PMC_CFRAME3_FDRI_SIZE 0x1000 -#define MM_PMC_CFRAME4_REG 0xf12d8000 -#define MM_PMC_CFRAME4_REG_SIZE 0x1000 -#define MM_PMC_CFRAME4_FDRI 0xf12d9000 -#define MM_PMC_CFRAME4_FDRI_SIZE 0x1000 -#define MM_PMC_CFRAME5_REG 0xf12da000 -#define MM_PMC_CFRAME5_REG_SIZE 0x1000 -#define MM_PMC_CFRAME5_FDRI 0xf12db000 -#define MM_PMC_CFRAME5_FDRI_SIZE 0x1000 -#define MM_PMC_CFRAME6_REG 0xf12dc000 -#define MM_PMC_CFRAME6_REG_SIZE 0x1000 -#define MM_PMC_CFRAME6_FDRI 0xf12dd000 -#define MM_PMC_CFRAME6_FDRI_SIZE 0x1000 -#define MM_PMC_CFRAME7_REG 0xf12de000 -#define MM_PMC_CFRAME7_REG_SIZE 0x1000 -#define MM_PMC_CFRAME7_FDRI 0xf12df000 -#define MM_PMC_CFRAME7_FDRI_SIZE 0x1000 -#define MM_PMC_CFRAME8_REG 0xf12e0000 -#define MM_PMC_CFRAME8_REG_SIZE 0x1000 -#define MM_PMC_CFRAME8_FDRI 0xf12e1000 -#define MM_PMC_CFRAME8_FDRI_SIZE 0x1000 -#define MM_PMC_CFRAME9_REG 0xf12e2000 -#define MM_PMC_CFRAME9_REG_SIZE 0x1000 -#define MM_PMC_CFRAME9_FDRI 0xf12e3000 -#define MM_PMC_CFRAME9_FDRI_SIZE 0x1000 -#define MM_PMC_CFRAME10_REG 0xf12e4000 -#define MM_PMC_CFRAME10_REG_SIZE 0x1000 -#define MM_PMC_CFRAME10_FDRI 0xf12e5000 -#define MM_PMC_CFRAME10_FDRI_SIZE 0x1000 -#define MM_PMC_CFRAME11_REG 0xf12e6000 -#define MM_PMC_CFRAME11_REG_SIZE 0x1000 -#define MM_PMC_CFRAME11_FDRI 0xf12e7000 -#define MM_PMC_CFRAME11_FDRI_SIZE 0x1000 -#define MM_PMC_CFRAME12_REG 0xf12e8000 -#define MM_PMC_CFRAME12_REG_SIZE 0x1000 -#define MM_PMC_CFRAME12_FDRI 0xf12e9000 -#define MM_PMC_CFRAME12_FDRI_SIZE 0x1000 -#define MM_PMC_CFRAME13_REG 0xf12ea000 -#define MM_PMC_CFRAME13_REG_SIZE 0x1000 -#define MM_PMC_CFRAME13_FDRI 0xf12eb000 -#define MM_PMC_CFRAME13_FDRI_SIZE 0x1000 -#define MM_PMC_CFRAME14_REG 0xf12ec000 -#define MM_PMC_CFRAME14_REG_SIZE 0x1000 -#define MM_PMC_CFRAME14_FDRI 0xf12ed000 -#define MM_PMC_CFRAME14_FDRI_SIZE 0x1000 -#define MM_PMC_CFRAME_BCAST_REG 0xf12ee000 -#define MM_PMC_CFRAME_BCAST_REG_SIZE 0x1000 -#define MM_PMC_CFRAME_BCAST_FDRI 0xf12ef000 -#define MM_PMC_CFRAME_BCAST_FDRI_SIZE 0x1000 + default: + g_assert_not_reached(); + } +} -#define MM_PMC_CRP 0xf1260000U -#define MM_PMC_CRP_SIZE 0x10000 -#define MM_PMC_RTC 0xf12a0000 -#define MM_PMC_RTC_SIZE 0x10000 -#define MM_PMC_TRNG 0xf1230000 -#define MM_PMC_TRNG_SIZE 0x10000 #endif diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h index c137ac5..a3117bd 100644 --- a/include/hw/arm/xlnx-zynqmp.h +++ b/include/hw/arm/xlnx-zynqmp.h @@ -42,6 +42,7 @@ #include "hw/misc/xlnx-zynqmp-crf.h" #include "hw/timer/cadence_ttc.h" #include "hw/usb/hcd-dwc3.h" +#include "hw/core/split-irq.h" #define TYPE_XLNX_ZYNQMP "xlnx-zynqmp" OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP) @@ -67,6 +68,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP) #define XLNX_ZYNQMP_OCM_RAM_SIZE 0x10000 #define XLNX_ZYNQMP_GIC_REGIONS 6 +#define XLNX_ZYNQMP_GIC_NUM_SPI_INTR 160 /* * ZynqMP maps the ARM GIC regions (GICC, GICD ...) at consecutive 64k offsets @@ -105,6 +107,9 @@ struct XlnxZynqMPState { GICState gic; MemoryRegion gic_mr[XLNX_ZYNQMP_GIC_REGIONS][XLNX_ZYNQMP_GIC_ALIASES]; + GICState rpu_gic; + SplitIRQ splitter[XLNX_ZYNQMP_GIC_NUM_SPI_INTR]; + MemoryRegion ocm_ram[XLNX_ZYNQMP_NUM_OCM_BANKS]; MemoryRegion *ddr_ram; diff --git a/include/hw/audio/asc.h b/include/hw/audio/asc.h index 04fac27..bb51e9a 100644 --- a/include/hw/audio/asc.h +++ b/include/hw/audio/asc.h @@ -14,7 +14,7 @@ #define HW_AUDIO_ASC_H #include "hw/sysbus.h" -#include "audio/audio.h" +#include "qemu/audio.h" #define ASC_FREQ 22257 @@ -61,7 +61,7 @@ struct ASCState { MemoryRegion mem_regs; MemoryRegion mem_extregs; - QEMUSoundCard card; + AudioBackend *audio_be; SWVoiceOut *voice; uint8_t *mixbuf; int samples; diff --git a/include/hw/audio/model.h b/include/hw/audio/model.h new file mode 100644 index 0000000..c38b359 --- /dev/null +++ b/include/hw/audio/model.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef HW_AUDIO_MODEL_H +#define HW_AUDIO_MODEL_H + +void audio_register_model_with_cb(const char *name, const char *descr, + void (*init_audio_model)(const char *audiodev)); +void audio_register_model(const char *name, const char *descr, + const char *typename); + +void audio_model_init(void); +void audio_print_available_models(void); +void audio_set_model(const char *name, const char *audiodev); + +#endif diff --git a/include/hw/audio/soundhw.h b/include/hw/audio/soundhw.h deleted file mode 100644 index 474c5ff..0000000 --- a/include/hw/audio/soundhw.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef HW_SOUNDHW_H -#define HW_SOUNDHW_H - -void pci_register_soundhw(const char *name, const char *descr, - int (*init_pci)(PCIBus *bus, const char *audiodev)); -void deprecated_register_soundhw(const char *name, const char *descr, - int isa, const char *typename); - -void soundhw_init(void); -void show_valid_soundhw(void); -void select_soundhw(const char *name, const char *audiodev); - -#endif diff --git a/include/hw/audio/virtio-snd.h b/include/hw/audio/virtio-snd.h index 8dafedb..c176066 100644 --- a/include/hw/audio/virtio-snd.h +++ b/include/hw/audio/virtio-snd.h @@ -17,7 +17,7 @@ #define QEMU_VIRTIO_SOUND_H #include "hw/virtio/virtio.h" -#include "audio/audio.h" +#include "qemu/audio.h" #include "standard-headers/linux/virtio_ids.h" #include "standard-headers/linux/virtio_snd.h" @@ -216,7 +216,7 @@ struct VirtIOSound { VirtQueue *queues[VIRTIO_SND_VQ_MAX]; uint64_t features; VirtIOSoundPCM *pcm; - QEMUSoundCard card; + AudioBackend *audio_be; VMChangeStateEntry *vmstate; virtio_snd_config snd_conf; QemuMutex cmdq_mutex; diff --git a/include/hw/block/block.h b/include/hw/block/block.h index de3946a..b4d9146 100644 --- a/include/hw/block/block.h +++ b/include/hw/block/block.h @@ -34,6 +34,8 @@ typedef struct BlockConf { OnOffAuto account_invalid, account_failed; BlockdevOnError rerror; BlockdevOnError werror; + uint32_t num_stats_intervals; + uint32_t *stats_intervals; } BlockConf; static inline unsigned int get_physical_block_exp(BlockConf *conf) @@ -66,7 +68,10 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf) DEFINE_PROP_ON_OFF_AUTO("account-invalid", _state, \ _conf.account_invalid, ON_OFF_AUTO_AUTO), \ DEFINE_PROP_ON_OFF_AUTO("account-failed", _state, \ - _conf.account_failed, ON_OFF_AUTO_AUTO) + _conf.account_failed, ON_OFF_AUTO_AUTO), \ + DEFINE_PROP_ARRAY("stats-intervals", _state, \ + _conf.num_stats_intervals, _conf.stats_intervals, \ + qdev_prop_uint32, uint32_t) #define DEFINE_BLOCK_PROPERTIES(_state, _conf) \ DEFINE_PROP_DRIVE("drive", _state, _conf.blk), \ diff --git a/include/hw/block/flash.h b/include/hw/block/flash.h index 5fd67f5..3671f01 100644 --- a/include/hw/block/flash.h +++ b/include/hw/block/flash.h @@ -44,24 +44,6 @@ PFlashCFI02 *pflash_cfi02_register(hwaddr base, uint16_t unlock_addr1, int be); -/* nand.c */ -DeviceState *nand_init(BlockBackend *blk, int manf_id, int chip_id); -void nand_setpins(DeviceState *dev, uint8_t cle, uint8_t ale, - uint8_t ce, uint8_t wp, uint8_t gnd); -void nand_getpins(DeviceState *dev, int *rb); -void nand_setio(DeviceState *dev, uint32_t value); -uint32_t nand_getio(DeviceState *dev); -uint32_t nand_getbuswidth(DeviceState *dev); - -#define NAND_MFR_TOSHIBA 0x98 -#define NAND_MFR_SAMSUNG 0xec -#define NAND_MFR_FUJITSU 0x04 -#define NAND_MFR_NATIONAL 0x8f -#define NAND_MFR_RENESAS 0x07 -#define NAND_MFR_STMICRO 0x20 -#define NAND_MFR_HYNIX 0xad -#define NAND_MFR_MICRON 0x2c - /* m25p80.c */ #define TYPE_M25P80 "m25p80-generic" diff --git a/include/hw/boards.h b/include/hw/boards.h index a7b1fcf..a48ed4f 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -26,6 +26,11 @@ OBJECT_DECLARE_TYPE(MachineState, MachineClass, MACHINE) extern MachineState *current_machine; /** + * machine_default_cpu_type: Return the machine default CPU type. + * @ms: Machine state + */ +const char *machine_default_cpu_type(const MachineState *ms); +/** * machine_class_default_cpu_type: Return the machine default CPU type. * @mc: Machine class */ @@ -250,15 +255,12 @@ typedef struct { * It also will be used as a way to option into "-m" option support. * If it's not set by board, '-m' will be ignored and generic code will * not create default RAM MemoryRegion. - * @fixup_ram_size: - * Amends user provided ram size (with -m option) using machine - * specific algorithm. To be used by old machine types for compat - * purposes only. - * Applies only to default memory backend, i.e., explicit memory backend - * wasn't used. * @smbios_memory_device_size: * Default size of memory device, * SMBIOS 3.1.0 "7.18 Memory Device (Type 17)" + * @get_valid_cpu_types: + * Returns a list of valid CPU types for this board. May be NULL + * if not needed. */ struct MachineClass { /*< private >*/ @@ -286,8 +288,7 @@ struct MachineClass { no_parallel:1, no_floppy:1, no_cdrom:1, - pci_allow_0_address:1, - legacy_fw_cfg_order:1; + pci_allow_0_address:1; bool auto_create_sdcard; bool is_default; const char *default_machine_opts; @@ -306,6 +307,8 @@ struct MachineClass { bool ignore_memory_transaction_failures; int numa_mem_align_shift; const char * const *valid_cpu_types; + GPtrArray *(*get_valid_cpu_types)(const MachineState *ms); + const char *(*get_default_cpu_type)(const MachineState *ms); strList *allowed_dynamic_sysbus_devices; bool auto_enable_numa_with_memhp; bool auto_enable_numa_with_memdev; @@ -326,7 +329,6 @@ struct MachineClass { unsigned cpu_index); const CPUArchIdList *(*possible_cpu_arch_ids)(MachineState *machine); int64_t (*get_default_cpu_node_id)(const MachineState *ms, int idx); - ram_addr_t (*fixup_ram_size)(ram_addr_t size); uint64_t smbios_memory_device_size; bool (*create_default_memdev)(MachineState *ms, const char *path, Error **errp); @@ -444,6 +446,7 @@ struct MachineState { SmpCache smp_cache; struct NVDIMMState *nvdimms_state; struct NumaState *numa_state; + bool acpi_spcr_enabled; }; /* @@ -503,6 +506,39 @@ struct MachineState { * DEFINE_VIRT_MACHINE_IMPL(false, major, minor, micro, _, tag) */ +#define DEFINE_MACHINE_EXTENDED(namestr, PARENT_NAME, InstanceName, \ + machine_initfn, ABSTRACT, ifaces...) \ + static void machine_initfn##_class_init(ObjectClass *oc, const void *data) \ + { \ + MachineClass *mc = MACHINE_CLASS(oc); \ + machine_initfn(mc); \ + } \ + static const TypeInfo machine_initfn##_typeinfo = { \ + .name = MACHINE_TYPE_NAME(namestr), \ + .parent = TYPE_##PARENT_NAME, \ + .class_init = machine_initfn##_class_init, \ + .instance_size = sizeof(InstanceName), \ + .abstract = ABSTRACT, \ + .interfaces = ifaces, \ + }; \ + static void machine_initfn##_register_types(void) \ + { \ + type_register_static(&machine_initfn##_typeinfo); \ + } \ + type_init(machine_initfn##_register_types) + +#define DEFINE_MACHINE(namestr, machine_initfn) \ + DEFINE_MACHINE_EXTENDED(namestr, MACHINE, MachineState, machine_initfn, \ + false, NULL) + +#define DEFINE_MACHINE_WITH_INTERFACE_ARRAY(namestr, machine_initfn, ifaces...)\ + DEFINE_MACHINE_EXTENDED(namestr, MACHINE, MachineState, machine_initfn, \ + false, ifaces) + +#define DEFINE_MACHINE_WITH_INTERFACES(namestr, machine_initfn, ...) \ + DEFINE_MACHINE_WITH_INTERFACE_ARRAY(namestr, machine_initfn, \ + (const InterfaceInfo[]) { __VA_ARGS__ }) + /* * Helper for dispatching different macros based on how * many __VA_ARGS__ are passed. Supports 1 to 5 variadic @@ -762,22 +798,8 @@ struct MachineState { } \ } while (0) -#define DEFINE_MACHINE(namestr, machine_initfn) \ - static void machine_initfn##_class_init(ObjectClass *oc, const void *data) \ - { \ - MachineClass *mc = MACHINE_CLASS(oc); \ - machine_initfn(mc); \ - } \ - static const TypeInfo machine_initfn##_typeinfo = { \ - .name = MACHINE_TYPE_NAME(namestr), \ - .parent = TYPE_MACHINE, \ - .class_init = machine_initfn##_class_init, \ - }; \ - static void machine_initfn##_register_types(void) \ - { \ - type_register_static(&machine_initfn##_typeinfo); \ - } \ - type_init(machine_initfn##_register_types) +extern GlobalProperty hw_compat_10_1[]; +extern const size_t hw_compat_10_1_len; extern GlobalProperty hw_compat_10_0[]; extern const size_t hw_compat_10_0_len; @@ -863,10 +885,4 @@ extern const size_t hw_compat_2_7_len; extern GlobalProperty hw_compat_2_6[]; extern const size_t hw_compat_2_6_len; -extern GlobalProperty hw_compat_2_5[]; -extern const size_t hw_compat_2_5_len; - -extern GlobalProperty hw_compat_2_4[]; -extern const size_t hw_compat_2_4_len; - #endif diff --git a/include/hw/char/avr_usart.h b/include/hw/char/avr_usart.h index 0cc599e..bd2d488 100644 --- a/include/hw/char/avr_usart.h +++ b/include/hw/char/avr_usart.h @@ -66,7 +66,7 @@ struct AVRUsartState { /* <public> */ MemoryRegion mmio; - CharBackend chr; + CharFrontend chr; bool enabled; diff --git a/include/hw/char/bcm2835_aux.h b/include/hw/char/bcm2835_aux.h index 9e08179..a11134f 100644 --- a/include/hw/char/bcm2835_aux.h +++ b/include/hw/char/bcm2835_aux.h @@ -24,7 +24,7 @@ struct BCM2835AuxState { /*< public >*/ MemoryRegion iomem; - CharBackend chr; + CharFrontend chr; qemu_irq irq; uint8_t read_fifo[BCM2835_AUX_RX_FIFO_LEN]; diff --git a/include/hw/char/cadence_uart.h b/include/hw/char/cadence_uart.h index e7f7cd8..c87c327 100644 --- a/include/hw/char/cadence_uart.h +++ b/include/hw/char/cadence_uart.h @@ -47,7 +47,7 @@ struct CadenceUARTState { uint32_t rx_count; uint32_t tx_count; uint64_t char_tx_time; - CharBackend chr; + CharFrontend chr; qemu_irq irq; QEMUTimer *fifo_trigger_handle; Clock *refclk; diff --git a/include/hw/char/cmsdk-apb-uart.h b/include/hw/char/cmsdk-apb-uart.h index 7de8f8d..3d0af26 100644 --- a/include/hw/char/cmsdk-apb-uart.h +++ b/include/hw/char/cmsdk-apb-uart.h @@ -25,7 +25,7 @@ struct CMSDKAPBUART { /*< public >*/ MemoryRegion iomem; - CharBackend chr; + CharFrontend chr; qemu_irq txint; qemu_irq rxint; qemu_irq txovrint; diff --git a/include/hw/char/digic-uart.h b/include/hw/char/digic-uart.h index f710a1a..3eebdab 100644 --- a/include/hw/char/digic-uart.h +++ b/include/hw/char/digic-uart.h @@ -38,7 +38,7 @@ struct DigicUartState { /*< public >*/ MemoryRegion regs_region; - CharBackend chr; + CharFrontend chr; uint32_t reg_rx; uint32_t reg_st; diff --git a/include/hw/char/escc.h b/include/hw/char/escc.h index 8c4c6a7..857f646 100644 --- a/include/hw/char/escc.h +++ b/include/hw/char/escc.h @@ -36,7 +36,7 @@ typedef struct ESCCChannelState { uint32_t reg; uint8_t wregs[ESCC_SERIAL_REGS], rregs[ESCC_SERIAL_REGS]; ESCCSERIOQueue queue; - CharBackend chr; + CharFrontend chr; int e0_mode, led_mode, caps_lock_mode, num_lock_mode; int disabled; int clock; diff --git a/include/hw/char/goldfish_tty.h b/include/hw/char/goldfish_tty.h index d59733e..70fdedd 100644 --- a/include/hw/char/goldfish_tty.h +++ b/include/hw/char/goldfish_tty.h @@ -24,7 +24,7 @@ struct GoldfishTTYState { MemoryRegion iomem; qemu_irq irq; - CharBackend chr; + CharFrontend chr; uint32_t data_len; uint64_t data_ptr; diff --git a/include/hw/char/ibex_uart.h b/include/hw/char/ibex_uart.h index 9deadf2..1ccbb60 100644 --- a/include/hw/char/ibex_uart.h +++ b/include/hw/char/ibex_uart.h @@ -64,7 +64,7 @@ struct IbexUartState { Clock *f_clk; - CharBackend chr; + CharFrontend chr; qemu_irq tx_watermark; qemu_irq rx_watermark; qemu_irq tx_empty; diff --git a/include/hw/char/imx_serial.h b/include/hw/char/imx_serial.h index 90ba3ff..2dcd2e6 100644 --- a/include/hw/char/imx_serial.h +++ b/include/hw/char/imx_serial.h @@ -122,7 +122,7 @@ struct IMXSerialState { uint32_t ucr4; qemu_irq irq; - CharBackend chr; + CharFrontend chr; }; #endif diff --git a/include/hw/char/max78000_uart.h b/include/hw/char/max78000_uart.h new file mode 100644 index 0000000..ac93f83 --- /dev/null +++ b/include/hw/char/max78000_uart.h @@ -0,0 +1,78 @@ +/* + * MAX78000 UART + * + * Copyright (c) 2025 Jackson Donaldson <jcksn@duck.com> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_MAX78000_UART_H +#define HW_MAX78000_UART_H + +#include "hw/sysbus.h" +#include "chardev/char-fe.h" +#include "qemu/fifo8.h" +#include "qom/object.h" + +#define UART_CTRL 0x0 +#define UART_STATUS 0x4 +#define UART_INT_EN 0x8 +#define UART_INT_FL 0xc +#define UART_CLKDIV 0x10 +#define UART_OSR 0x14 +#define UART_TXPEEK 0x18 +#define UART_PNR 0x1c +#define UART_FIFO 0x20 +#define UART_DMA 0x30 +#define UART_WKEN 0x34 +#define UART_WKFL 0x38 + +/* CTRL */ +#define UART_CTF_DIS (1 << 7) +#define UART_FLUSH_TX (1 << 8) +#define UART_FLUSH_RX (1 << 9) +#define UART_BCLKEN (1 << 15) +#define UART_BCLKRDY (1 << 19) + +/* STATUS */ +#define UART_RX_LVL 8 +#define UART_TX_EM (1 << 6) +#define UART_RX_FULL (1 << 5) +#define UART_RX_EM (1 << 4) + +/* PNR (Pin Control Register) */ +#define UART_CTS 1 +#define UART_RTS (1 << 1) + +/* INT_EN / INT_FL */ +#define UART_RX_THD (1 << 4) +#define UART_TX_HE (1 << 6) + +#define UART_RXBUFLEN 0x100 +#define TYPE_MAX78000_UART "max78000-uart" +OBJECT_DECLARE_SIMPLE_TYPE(Max78000UartState, MAX78000_UART) + +struct Max78000UartState { + SysBusDevice parent_obj; + + MemoryRegion mmio; + + uint32_t ctrl; + uint32_t status; + uint32_t int_en; + uint32_t int_fl; + uint32_t clkdiv; + uint32_t osr; + uint32_t txpeek; + uint32_t pnr; + uint32_t fifo; + uint32_t dma; + uint32_t wken; + uint32_t wkfl; + + Fifo8 rx_fifo; + + CharFrontend chr; + qemu_irq irq; +}; +#endif /* HW_STM32F2XX_USART_H */ diff --git a/include/hw/char/nrf51_uart.h b/include/hw/char/nrf51_uart.h index 561b638..03d8c2a 100644 --- a/include/hw/char/nrf51_uart.h +++ b/include/hw/char/nrf51_uart.h @@ -59,7 +59,7 @@ struct NRF51UARTState { SysBusDevice parent_obj; MemoryRegion iomem; - CharBackend chr; + CharFrontend chr; qemu_irq irq; guint watch_tag; diff --git a/include/hw/char/parallel.h b/include/hw/char/parallel.h index 7b04478..3f8d9b5 100644 --- a/include/hw/char/parallel.h +++ b/include/hw/char/parallel.h @@ -15,7 +15,7 @@ typedef struct ParallelState { uint8_t control; qemu_irq irq; int irq_pending; - CharBackend chr; + CharFrontend chr; int hw_driver; int epp_timeout; uint32_t last_read_offset; /* For debugging */ diff --git a/include/hw/char/pl011.h b/include/hw/char/pl011.h index 299ca9b..2d4ff01 100644 --- a/include/hw/char/pl011.h +++ b/include/hw/char/pl011.h @@ -47,7 +47,7 @@ struct PL011State { int read_pos; int read_count; int read_trigger; - CharBackend chr; + CharFrontend chr; qemu_irq irq[6]; Clock *clk; bool migrate_clk; diff --git a/include/hw/char/renesas_sci.h b/include/hw/char/renesas_sci.h index a4764e3..90e784f 100644 --- a/include/hw/char/renesas_sci.h +++ b/include/hw/char/renesas_sci.h @@ -33,7 +33,7 @@ struct RSCIState { MemoryRegion memory; QEMUTimer timer; - CharBackend chr; + CharFrontend chr; qemu_irq irq[SCI_NR_IRQ]; uint8_t smr; diff --git a/include/hw/char/riscv_htif.h b/include/hw/char/riscv_htif.h index ee0ca29..9d61e60 100644 --- a/include/hw/char/riscv_htif.h +++ b/include/hw/char/riscv_htif.h @@ -36,7 +36,7 @@ typedef struct HTIFState { hwaddr fromhost_offset; MemoryRegion mmio; - CharBackend chr; + CharFrontend chr; uint64_t pending_read; } HTIFState; diff --git a/include/hw/char/serial.h b/include/hw/char/serial.h index 4bf90a4..b804e22 100644 --- a/include/hw/char/serial.h +++ b/include/hw/char/serial.h @@ -54,7 +54,7 @@ struct SerialState { it can be reset while reading iir */ int thr_ipending; qemu_irq irq; - CharBackend chr; + CharFrontend chr; int last_break_enable; uint32_t baudbase; uint32_t tsr_retry; @@ -77,7 +77,6 @@ struct SerialState { QEMUTimer *modem_status_poll; MemoryRegion io; }; -typedef struct SerialState SerialState; extern const VMStateDescription vmstate_serial; extern const MemoryRegionOps serial_io_ops; diff --git a/include/hw/char/shakti_uart.h b/include/hw/char/shakti_uart.h index 526c408..e5e775d 100644 --- a/include/hw/char/shakti_uart.h +++ b/include/hw/char/shakti_uart.h @@ -68,7 +68,7 @@ typedef struct { uint32_t uart_iq_cycles; uint32_t uart_rx_threshold; - CharBackend chr; + CharFrontend chr; } ShaktiUartState; #endif /* HW_SHAKTI_UART_H */ diff --git a/include/hw/char/sifive_uart.h b/include/hw/char/sifive_uart.h index 0846cf6..6486c3f 100644 --- a/include/hw/char/sifive_uart.h +++ b/include/hw/char/sifive_uart.h @@ -67,7 +67,7 @@ struct SiFiveUARTState { /*< public >*/ qemu_irq irq; MemoryRegion mmio; - CharBackend chr; + CharFrontend chr; uint32_t txfifo; uint32_t ie; diff --git a/include/hw/char/stm32f2xx_usart.h b/include/hw/char/stm32f2xx_usart.h index fdfa742..f9018b8 100644 --- a/include/hw/char/stm32f2xx_usart.h +++ b/include/hw/char/stm32f2xx_usart.h @@ -73,7 +73,7 @@ struct STM32F2XXUsartState { uint32_t usart_cr3; uint32_t usart_gtpr; - CharBackend chr; + CharFrontend chr; qemu_irq irq; }; #endif /* HW_STM32F2XX_USART_H */ diff --git a/include/hw/char/stm32l4x5_usart.h b/include/hw/char/stm32l4x5_usart.h index dd38666..cdf7419 100644 --- a/include/hw/char/stm32l4x5_usart.h +++ b/include/hw/char/stm32l4x5_usart.h @@ -53,7 +53,7 @@ struct Stm32l4x5UsartBaseState { uint32_t tdr; Clock *clk; - CharBackend chr; + CharFrontend chr; qemu_irq irq; guint watch_tag; }; diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index 1e87f7d..9615051 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -169,7 +169,7 @@ struct CPUClass { vaddr (*gdb_adjust_breakpoint)(CPUState *cpu, vaddr addr); const char *gdb_core_xml_file; - const gchar * (*gdb_arch_name)(CPUState *cpu); + const char * (*gdb_arch_name)(CPUState *cpu); const char * (*gdb_get_core_xml_file)(CPUState *cpu); void (*disas_set_info)(CPUState *cpu, disassemble_info *info); @@ -198,10 +198,11 @@ struct CPUClass { }; /* - * Fix the number of mmu modes to 16, which is also the maximum - * supported by the softmmu tlb api. + * Fix the number of mmu modes across all targets. + * Current maximum is target/arm/. */ -#define NB_MMU_MODES 16 +#define NB_MMU_MODES 22 +typedef uint32_t MMUIdxMap; /* Use a fully associative victim tlb of 8 entries. */ #define CPU_VTLB_SIZE 8 @@ -306,7 +307,7 @@ typedef struct CPUTLBCommon { * mmu_idx N since the last time that mmu_idx was flushed. * Protected by tlb_c.lock. */ - uint16_t dirty; + MMUIdxMap dirty; /* * Statistics. These are not lock protected, but are read and * written atomically. This allows the monitor to print a snapshot @@ -368,6 +369,7 @@ typedef struct CPUNegativeOffsetState { GArray *plugin_mem_cbs; uint64_t plugin_mem_value_low; uint64_t plugin_mem_value_high; + int32_t plugin_cb_flags; #endif IcountDecr icount_decr; bool can_do_io; @@ -421,7 +423,17 @@ struct qemu_work_item; * valid under cpu_list_lock. * @created: Indicates whether the CPU thread has been successfully created. * @halt_cond: condition variable sleeping threads can wait on. + * @exit_request: Another thread requests the CPU to call qemu_process_cpu_events(). + * Should be read only by CPU thread with load-acquire, to synchronize with + * other threads' store-release operation. + * + * In some cases, accelerator-specific code will write exit_request from + * within the same thread, to "bump" the effect of qemu_cpu_kick() to + * the one provided by cpu_exit(), especially when processing interrupt + * flags. In this case, the write and read happen in the same thread + * and the write therefore can use qemu_atomic_set(). * @interrupt_request: Indicates a pending interrupt request. + * Only used by system emulation. * @halted: Nonzero if the CPU is in suspended state. * @stop: Indicates a pending stop request. * @stopped: Indicates the CPU has been artificially stopped. @@ -441,6 +453,7 @@ struct qemu_work_item; * @opaque: User data. * @mem_io_pc: Host Program Counter at which the memory was accessed. * @accel: Pointer to accelerator specific state. + * @vcpu_dirty: Hardware accelerator is not synchronized with QEMU state * @kvm_fd: vCPU file descriptor for KVM. * @work_mutex: Lock to prevent multiple access to @work_list. * @work_list: List of pending asynchronous work. @@ -492,7 +505,6 @@ struct CPUState { bool exit_request; int exclusive_context_count; uint32_t cflags_next_tb; - /* updates protected by BQL */ uint32_t interrupt_request; int singlestep_enabled; int64_t icount_budget; @@ -504,7 +516,6 @@ struct CPUState { QSIMPLEQ_HEAD(, qemu_work_item) work_list; struct CPUAddressSpace *cpu_ases; - int cpu_ases_count; int num_ases; AddressSpace *as; MemoryRegion *memory; @@ -537,7 +548,6 @@ struct CPUState { uint32_t kvm_fetch_index; uint64_t dirty_pages; int kvm_vcpu_stats_fd; - bool vcpu_dirty; /* Use by accel-block: CPU is executing an ioctl() */ QemuLockCnt in_ioctl_lock; @@ -553,6 +563,7 @@ struct CPUState { uint32_t halted; int32_t exception_index; + bool vcpu_dirty; AccelCPUState *accel; /* Used to keep track of an outstanding cpu throttle thread for migration @@ -591,6 +602,22 @@ static inline CPUArchState *cpu_env(CPUState *cpu) return (CPUArchState *)(cpu + 1); } +#ifdef CONFIG_TCG +/* + * Invert the index order of the CPUTLBDescFast array so that lower + * mmu_idx have offsets from env with smaller magnitude. + */ +static inline int mmuidx_to_fast_index(int mmu_idx) +{ + return NB_MMU_MODES - 1 - mmu_idx; +} + +static inline CPUTLBDescFast *cpu_tlb_fast(CPUState *cpu, int mmu_idx) +{ + return &cpu->neg.tlb.f[mmuidx_to_fast_index(mmu_idx)]; +} +#endif + typedef QTAILQ_HEAD(CPUTailQ, CPUState) CPUTailQ; extern CPUTailQ cpus_queue; @@ -662,6 +689,26 @@ int cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu, void *opaque); /** + * cpu_memory_rw_debug: + * @cpu: The CPU whose memory is to be accessed + * @addr: guest virtual address + * @ptr: buffer with the data transferred + * @len: the number of bytes to read or write + * @is_write: indicates the transfer direction + * + * Take a virtual address, convert it to a physical address via + * an MMU lookup using the current settings of the specified CPU, + * and then perform the access (using address_space_rw() for + * reads or address_space_write_rom() for writes). + * + * This function is intended for use by the GDB stub and similar code. + * + * Returns: 0 on success, -1 on error + */ +int cpu_memory_rw_debug(CPUState *cpu, vaddr addr, + void *ptr, size_t len, bool is_write); + +/** * cpu_get_crash_info: * @cpu: The CPU to get crash information for * @@ -827,7 +874,8 @@ bool qemu_cpu_is_self(CPUState *cpu); * qemu_cpu_kick: * @cpu: The vCPU to kick. * - * Kicks @cpu's thread. + * Kicks @cpu's thread to exit the accelerator. For accelerators that + * can do that, the target vCPU thread will try not to take the BQL. */ void qemu_cpu_kick(CPUState *cpu); @@ -941,6 +989,28 @@ CPUState *cpu_by_arch_id(int64_t id); void cpu_interrupt(CPUState *cpu, int mask); /** + * cpu_test_interrupt: + * @cpu: The CPU to check interrupt(s) on. + * @mask: The interrupts to check. + * + * Checks if any of interrupts in @mask are pending on @cpu. + */ +static inline bool cpu_test_interrupt(CPUState *cpu, int mask) +{ + return qatomic_load_acquire(&cpu->interrupt_request) & mask; +} + +/** + * cpu_set_interrupt: + * @cpu: The CPU to set pending interrupt(s) on. + * @mask: The interrupts to set. + * + * Sets interrupts in @mask as pending on @cpu. Unlike @cpu_interrupt, + * this does not kick the vCPU. + */ +void cpu_set_interrupt(CPUState *cpu, int mask); + +/** * cpu_set_pc: * @cpu: The CPU to set the program counter for. * @addr: Program counter value. @@ -1111,6 +1181,15 @@ AddressSpace *cpu_get_address_space(CPUState *cpu, int asidx); G_NORETURN void cpu_abort(CPUState *cpu, const char *fmt, ...) G_GNUC_PRINTF(2, 3); +/** + * qemu_process_cpu_events: + * @cpu: CPU that left the execution loop + * + * Perform accelerator-independent work after the CPU has left + * the inner execution loop. + */ +void qemu_process_cpu_events(CPUState *cpu); + /* $(top_srcdir)/cpu.c */ void cpu_class_init_props(DeviceClass *dc); void cpu_exec_class_post_init(CPUClass *cc); @@ -1126,4 +1205,10 @@ extern const VMStateDescription vmstate_cpu_common; #define UNASSIGNED_CPU_INDEX -1 #define UNASSIGNED_CLUSTER_INDEX -1 +enum CacheType { + DATA_CACHE, + INSTRUCTION_CACHE, + UNIFIED_CACHE +}; + #endif diff --git a/include/hw/core/resetcontainer.h b/include/hw/core/resetcontainer.h index 23db0c7..daeb18c 100644 --- a/include/hw/core/resetcontainer.h +++ b/include/hw/core/resetcontainer.h @@ -20,7 +20,7 @@ #include "qom/object.h" #define TYPE_RESETTABLE_CONTAINER "resettable-container" -OBJECT_DECLARE_TYPE(ResettableContainer, ResettableContainerClass, RESETTABLE_CONTAINER) +OBJECT_DECLARE_SIMPLE_TYPE(ResettableContainer, RESETTABLE_CONTAINER) /** * resettable_container_add: Add a resettable object to the container diff --git a/include/hw/cxl/cxl.h b/include/hw/cxl/cxl.h index 75e47b6..998f495 100644 --- a/include/hw/cxl/cxl.h +++ b/include/hw/cxl/cxl.h @@ -23,10 +23,13 @@ #define CXL_DEVICE_REG_BAR_IDX 2 #define CXL_WINDOW_MAX 10 +#define CXL_NUM_EXTENTS_SUPPORTED 512 typedef struct PXBCXLDev PXBCXLDev; typedef struct CXLFixedWindow { + SysBusDevice parent_obj; + int index; uint64_t size; char **targets; PXBCXLDev *target_hbs[16]; @@ -37,12 +40,13 @@ typedef struct CXLFixedWindow { MemoryRegion mr; hwaddr base; } CXLFixedWindow; +#define TYPE_CXL_FMW "cxl-fmw" +OBJECT_DECLARE_SIMPLE_TYPE(CXLFixedWindow, CXL_FMW) typedef struct CXLState { bool is_enabled; MemoryRegion host_mr; unsigned int next_mr_idx; - GList *fixed_windows; CXLFixedMemoryWindowOptionsList *cfmw_list; } CXLState; diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h index ed6cd50..89411c8 100644 --- a/include/hw/cxl/cxl_device.h +++ b/include/hw/cxl/cxl_device.h @@ -133,6 +133,15 @@ typedef enum { CXL_MBOX_MAX = 0x20 } CXLRetCode; +/* r3.2 Section 7.6.7.6.2: Table 7-66: DSMAS Flags Bits */ +typedef enum { + CXL_DSMAS_FLAGS_NONVOLATILE = 2, + CXL_DSMAS_FLAGS_SHARABLE = 3, + CXL_DSMAS_FLAGS_HW_MANAGED_COHERENCY = 4, + CXL_DSMAS_FLAGS_IC_SPECIFIC_DC_MANAGEMENT = 5, + CXL_DSMAS_FLAGS_RDONLY = 6, +} CXLDSMASFlags; + typedef struct CXLCCI CXLCCI; typedef struct cxl_device_state CXLDeviceState; struct cxl_cmd; @@ -530,6 +539,14 @@ typedef struct CXLDCRegion { uint32_t dsmadhandle; uint8_t flags; unsigned long *blk_bitmap; + uint64_t supported_blk_size_bitmask; + QemuMutex bitmap_lock; + /* Following bools make up dsmas flags, as defined in the CDAT */ + bool nonvolatile; + bool sharable; + bool hw_managed_coherency; + bool ic_specific_dc_management; + bool rdonly; } CXLDCRegion; typedef struct CXLSetFeatureInfo { @@ -618,6 +635,7 @@ struct CXLType3Dev { CXLDCExtentList extents; CXLDCExtentGroupList extents_pending; uint32_t total_extent_count; + uint32_t nr_extents_accepted; uint32_t ext_list_gen_seq; uint8_t num_regions; /* 0-8 regions */ @@ -696,11 +714,22 @@ CXLDCExtentGroup *cxl_insert_extent_to_extent_group(CXLDCExtentGroup *group, uint16_t shared_seq); void cxl_extent_group_list_insert_tail(CXLDCExtentGroupList *list, CXLDCExtentGroup *group); -void cxl_extent_group_list_delete_front(CXLDCExtentGroupList *list); +uint32_t cxl_extent_group_list_delete_front(CXLDCExtentGroupList *list); void ct3_set_region_block_backed(CXLType3Dev *ct3d, uint64_t dpa, uint64_t len); void ct3_clear_region_block_backed(CXLType3Dev *ct3d, uint64_t dpa, uint64_t len); bool ct3_test_region_block_backed(CXLType3Dev *ct3d, uint64_t dpa, uint64_t len); +void cxl_assign_event_header(CXLEventRecordHdr *hdr, + const QemuUUID *uuid, uint32_t flags, + uint8_t length, uint64_t timestamp); +void cxl_create_dc_event_records_for_extents(CXLType3Dev *ct3d, + CXLDCEventType type, + CXLDCExtentRaw extents[], + uint32_t ext_count); +bool cxl_extents_overlaps_dpa_range(CXLDCExtentList *list, + uint64_t dpa, uint64_t len); +bool cxl_extent_groups_overlaps_dpa_range(CXLDCExtentGroupList *list, + uint64_t dpa, uint64_t len); #endif diff --git a/include/hw/cxl/cxl_events.h b/include/hw/cxl/cxl_events.h index 38cadaa..758b075 100644 --- a/include/hw/cxl/cxl_events.h +++ b/include/hw/cxl/cxl_events.h @@ -184,4 +184,19 @@ typedef struct CXLEventDynamicCapacity { uint32_t tags_avail; } QEMU_PACKED CXLEventDynamicCapacity; +/* CXL r3.1 Table 8-50: Dynamic Capacity Event Record */ +static const QemuUUID dynamic_capacity_uuid = { + .data = UUID(0xca95afa7, 0xf183, 0x4018, 0x8c, 0x2f, + 0x95, 0x26, 0x8e, 0x10, 0x1a, 0x2a), +}; + +typedef enum CXLDCEventType { + DC_EVENT_ADD_CAPACITY = 0x0, + DC_EVENT_RELEASE_CAPACITY = 0x1, + DC_EVENT_FORCED_RELEASE_CAPACITY = 0x2, + DC_EVENT_REGION_CONFIG_UPDATED = 0x3, + DC_EVENT_ADD_CAPACITY_RSP = 0x4, + DC_EVENT_CAPACITY_RELEASED = 0x5, +} CXLDCEventType; + #endif /* CXL_EVENTS_H */ diff --git a/include/hw/cxl/cxl_host.h b/include/hw/cxl/cxl_host.h index c9bc9c7..cd3c368 100644 --- a/include/hw/cxl/cxl_host.h +++ b/include/hw/cxl/cxl_host.h @@ -14,8 +14,11 @@ #define CXL_HOST_H void cxl_machine_init(Object *obj, CXLState *state); -void cxl_fmws_link_targets(CXLState *stat, Error **errp); +void cxl_fmws_link_targets(Error **errp); void cxl_hook_up_pxb_registers(PCIBus *bus, CXLState *state, Error **errp); +hwaddr cxl_fmws_set_memmap(hwaddr base, hwaddr max_addr); +void cxl_fmws_update_mmio(void); +GSList *cxl_fmws_get_all_sorted(void); extern const MemoryRegionOps cfmws_ops; diff --git a/include/hw/cxl/cxl_mailbox.h b/include/hw/cxl/cxl_mailbox.h index 9008402..a05d7cb 100644 --- a/include/hw/cxl/cxl_mailbox.h +++ b/include/hw/cxl/cxl_mailbox.h @@ -8,6 +8,7 @@ #ifndef CXL_MAILBOX_H #define CXL_MAILBOX_H +#define CXL_MBOX_CONFIG_CHANGE_COLD_RESET (1) #define CXL_MBOX_IMMEDIATE_CONFIG_CHANGE (1 << 1) #define CXL_MBOX_IMMEDIATE_DATA_CHANGE (1 << 2) #define CXL_MBOX_IMMEDIATE_POLICY_CHANGE (1 << 3) @@ -15,5 +16,10 @@ #define CXL_MBOX_SECURITY_STATE_CHANGE (1 << 5) #define CXL_MBOX_BACKGROUND_OPERATION (1 << 6) #define CXL_MBOX_BACKGROUND_OPERATION_ABORT (1 << 7) +#define CXL_MBOX_SECONDARY_MBOX_SUPPORTED (1 << 8) +#define CXL_MBOX_REQUEST_ABORT_BACKGROUND_OP_SUPPORTED (1 << 9) +#define CXL_MBOX_CEL_10_TO_11_VALID (1 << 10) +#define CXL_MBOX_CONFIG_CHANGE_CONV_RESET (1 << 11) +#define CXL_MBOX_CONFIG_CHANGE_CXL_RESET (1 << 12) #endif diff --git a/include/hw/display/bcm2835_fb.h b/include/hw/display/bcm2835_fb.h index 49541bf..acc9230 100644 --- a/include/hw/display/bcm2835_fb.h +++ b/include/hw/display/bcm2835_fb.h @@ -13,7 +13,6 @@ #define BCM2835_FB_H #include "hw/sysbus.h" -#include "ui/console.h" #include "qom/object.h" #define UPPER_RAM_BASE 0x40000000 diff --git a/include/hw/display/edid.h b/include/hw/display/edid.h index 520f8ec..91c0a42 100644 --- a/include/hw/display/edid.h +++ b/include/hw/display/edid.h @@ -1,6 +1,8 @@ #ifndef EDID_H #define EDID_H +#define EDID_NAME_MAX_LENGTH 12 + typedef struct qemu_edid_info { const char *vendor; /* http://www.uefi.org/pnp_id_list */ const char *name; diff --git a/include/hw/display/ramfb.h b/include/hw/display/ramfb.h index a7e0019..172aa6d 100644 --- a/include/hw/display/ramfb.h +++ b/include/hw/display/ramfb.h @@ -6,7 +6,7 @@ /* ramfb.c */ typedef struct RAMFBState RAMFBState; void ramfb_display_update(QemuConsole *con, RAMFBState *s); -RAMFBState *ramfb_setup(Error **errp); +RAMFBState *ramfb_setup(bool romfile, Error **errp); extern const VMStateDescription ramfb_vmstate; diff --git a/include/hw/display/xlnx_dp.h b/include/hw/display/xlnx_dp.h index e86a87f..af859e4 100644 --- a/include/hw/display/xlnx_dp.h +++ b/include/hw/display/xlnx_dp.h @@ -33,7 +33,7 @@ #include "qemu/fifo8.h" #include "qemu/units.h" #include "hw/dma/xlnx_dpdma.h" -#include "audio/audio.h" +#include "qemu/audio.h" #include "qom/object.h" #include "hw/ptimer.h" @@ -84,7 +84,7 @@ struct XlnxDPState { struct PixmanPlane v_plane; struct PixmanPlane bout_plane; - QEMUSoundCard aud_card; + AudioBackend *audio_be; SWVoiceOut *amixer_output_stream; int16_t audio_buffer_0[AUD_CHBUF_MAX_DEPTH]; int16_t audio_buffer_1[AUD_CHBUF_MAX_DEPTH]; diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h index f066ab7..3ea732f 100644 --- a/include/hw/firmware/smbios.h +++ b/include/hw/firmware/smbios.h @@ -22,7 +22,7 @@ extern GArray *usr_blobs_sizes; typedef struct { const char *vendor, *version, *date; - bool have_major_minor, uefi; + bool have_major_minor, uefi, vm; uint8_t major, minor; } smbios_type0_t; extern smbios_type0_t smbios_type0; diff --git a/include/hw/gpio/aspeed_gpio.h b/include/hw/gpio/aspeed_gpio.h index e1e6c54..e6b2fe7 100644 --- a/include/hw/gpio/aspeed_gpio.h +++ b/include/hw/gpio/aspeed_gpio.h @@ -70,7 +70,7 @@ typedef struct AspeedGPIOReg { } AspeedGPIOReg; struct AspeedGPIOClass { - SysBusDevice parent_obj; + SysBusDeviceClass parent_class; const GPIOSetProperties *props; uint32_t nr_gpio_pins; uint32_t nr_gpio_sets; diff --git a/include/hw/hyperv/hvgdk.h b/include/hw/hyperv/hvgdk.h new file mode 100644 index 0000000..71161f4 --- /dev/null +++ b/include/hw/hyperv/hvgdk.h @@ -0,0 +1,20 @@ +/* + * Type definitions for the mshv guest interface. + * + * Copyright Microsoft, Corp. 2025 + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_HYPERV_HVGDK_H +#define HW_HYPERV_HVGDK_H + +#define HVGDK_H_VERSION (25125) + +enum hv_unimplemented_msr_action { + HV_UNIMPLEMENTED_MSR_ACTION_FAULT = 0, + HV_UNIMPLEMENTED_MSR_ACTION_IGNORE_WRITE_READ_ZERO = 1, + HV_UNIMPLEMENTED_MSR_ACTION_COUNT = 2, +}; + +#endif /* HW_HYPERV_HVGDK_H */ diff --git a/include/hw/hyperv/hvgdk_mini.h b/include/hw/hyperv/hvgdk_mini.h new file mode 100644 index 0000000..d89315f --- /dev/null +++ b/include/hw/hyperv/hvgdk_mini.h @@ -0,0 +1,817 @@ +/* + * Userspace interfaces for /dev/mshv* devices and derived fds + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_HYPERV_HVGDK_MINI_H +#define HW_HYPERV_HVGDK_MINI_H + +#define MSHV_IOCTL 0xB8 + +typedef enum hv_register_name { + /* Pending Interruption Register */ + HV_REGISTER_PENDING_INTERRUPTION = 0x00010002, + + /* X64 User-Mode Registers */ + HV_X64_REGISTER_RAX = 0x00020000, + HV_X64_REGISTER_RCX = 0x00020001, + HV_X64_REGISTER_RDX = 0x00020002, + HV_X64_REGISTER_RBX = 0x00020003, + HV_X64_REGISTER_RSP = 0x00020004, + HV_X64_REGISTER_RBP = 0x00020005, + HV_X64_REGISTER_RSI = 0x00020006, + HV_X64_REGISTER_RDI = 0x00020007, + HV_X64_REGISTER_R8 = 0x00020008, + HV_X64_REGISTER_R9 = 0x00020009, + HV_X64_REGISTER_R10 = 0x0002000A, + HV_X64_REGISTER_R11 = 0x0002000B, + HV_X64_REGISTER_R12 = 0x0002000C, + HV_X64_REGISTER_R13 = 0x0002000D, + HV_X64_REGISTER_R14 = 0x0002000E, + HV_X64_REGISTER_R15 = 0x0002000F, + HV_X64_REGISTER_RIP = 0x00020010, + HV_X64_REGISTER_RFLAGS = 0x00020011, + + /* X64 Floating Point and Vector Registers */ + HV_X64_REGISTER_XMM0 = 0x00030000, + HV_X64_REGISTER_XMM1 = 0x00030001, + HV_X64_REGISTER_XMM2 = 0x00030002, + HV_X64_REGISTER_XMM3 = 0x00030003, + HV_X64_REGISTER_XMM4 = 0x00030004, + HV_X64_REGISTER_XMM5 = 0x00030005, + HV_X64_REGISTER_XMM6 = 0x00030006, + HV_X64_REGISTER_XMM7 = 0x00030007, + HV_X64_REGISTER_XMM8 = 0x00030008, + HV_X64_REGISTER_XMM9 = 0x00030009, + HV_X64_REGISTER_XMM10 = 0x0003000A, + HV_X64_REGISTER_XMM11 = 0x0003000B, + HV_X64_REGISTER_XMM12 = 0x0003000C, + HV_X64_REGISTER_XMM13 = 0x0003000D, + HV_X64_REGISTER_XMM14 = 0x0003000E, + HV_X64_REGISTER_XMM15 = 0x0003000F, + HV_X64_REGISTER_FP_MMX0 = 0x00030010, + HV_X64_REGISTER_FP_MMX1 = 0x00030011, + HV_X64_REGISTER_FP_MMX2 = 0x00030012, + HV_X64_REGISTER_FP_MMX3 = 0x00030013, + HV_X64_REGISTER_FP_MMX4 = 0x00030014, + HV_X64_REGISTER_FP_MMX5 = 0x00030015, + HV_X64_REGISTER_FP_MMX6 = 0x00030016, + HV_X64_REGISTER_FP_MMX7 = 0x00030017, + HV_X64_REGISTER_FP_CONTROL_STATUS = 0x00030018, + HV_X64_REGISTER_XMM_CONTROL_STATUS = 0x00030019, + + /* X64 Control Registers */ + HV_X64_REGISTER_CR0 = 0x00040000, + HV_X64_REGISTER_CR2 = 0x00040001, + HV_X64_REGISTER_CR3 = 0x00040002, + HV_X64_REGISTER_CR4 = 0x00040003, + HV_X64_REGISTER_CR8 = 0x00040004, + HV_X64_REGISTER_XFEM = 0x00040005, + + /* X64 Segment Registers */ + HV_X64_REGISTER_ES = 0x00060000, + HV_X64_REGISTER_CS = 0x00060001, + HV_X64_REGISTER_SS = 0x00060002, + HV_X64_REGISTER_DS = 0x00060003, + HV_X64_REGISTER_FS = 0x00060004, + HV_X64_REGISTER_GS = 0x00060005, + HV_X64_REGISTER_LDTR = 0x00060006, + HV_X64_REGISTER_TR = 0x00060007, + + /* X64 Table Registers */ + HV_X64_REGISTER_IDTR = 0x00070000, + HV_X64_REGISTER_GDTR = 0x00070001, + + /* X64 Virtualized MSRs */ + HV_X64_REGISTER_TSC = 0x00080000, + HV_X64_REGISTER_EFER = 0x00080001, + HV_X64_REGISTER_KERNEL_GS_BASE = 0x00080002, + HV_X64_REGISTER_APIC_BASE = 0x00080003, + HV_X64_REGISTER_PAT = 0x00080004, + HV_X64_REGISTER_SYSENTER_CS = 0x00080005, + HV_X64_REGISTER_SYSENTER_EIP = 0x00080006, + HV_X64_REGISTER_SYSENTER_ESP = 0x00080007, + HV_X64_REGISTER_STAR = 0x00080008, + HV_X64_REGISTER_LSTAR = 0x00080009, + HV_X64_REGISTER_CSTAR = 0x0008000A, + HV_X64_REGISTER_SFMASK = 0x0008000B, + HV_X64_REGISTER_INITIAL_APIC_ID = 0x0008000C, + + /* X64 Cache control MSRs */ + HV_X64_REGISTER_MSR_MTRR_CAP = 0x0008000D, + HV_X64_REGISTER_MSR_MTRR_DEF_TYPE = 0x0008000E, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE0 = 0x00080010, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE1 = 0x00080011, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE2 = 0x00080012, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE3 = 0x00080013, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE4 = 0x00080014, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE5 = 0x00080015, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE6 = 0x00080016, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE7 = 0x00080017, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE8 = 0x00080018, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE9 = 0x00080019, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASEA = 0x0008001A, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASEB = 0x0008001B, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASEC = 0x0008001C, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASED = 0x0008001D, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASEE = 0x0008001E, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASEF = 0x0008001F, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK0 = 0x00080040, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK1 = 0x00080041, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK2 = 0x00080042, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK3 = 0x00080043, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK4 = 0x00080044, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK5 = 0x00080045, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK6 = 0x00080046, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK7 = 0x00080047, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK8 = 0x00080048, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK9 = 0x00080049, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASKA = 0x0008004A, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASKB = 0x0008004B, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASKC = 0x0008004C, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASKD = 0x0008004D, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASKE = 0x0008004E, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASKF = 0x0008004F, + HV_X64_REGISTER_MSR_MTRR_FIX64K00000 = 0x00080070, + HV_X64_REGISTER_MSR_MTRR_FIX16K80000 = 0x00080071, + HV_X64_REGISTER_MSR_MTRR_FIX16KA0000 = 0x00080072, + HV_X64_REGISTER_MSR_MTRR_FIX4KC0000 = 0x00080073, + HV_X64_REGISTER_MSR_MTRR_FIX4KC8000 = 0x00080074, + HV_X64_REGISTER_MSR_MTRR_FIX4KD0000 = 0x00080075, + HV_X64_REGISTER_MSR_MTRR_FIX4KD8000 = 0x00080076, + HV_X64_REGISTER_MSR_MTRR_FIX4KE0000 = 0x00080077, + HV_X64_REGISTER_MSR_MTRR_FIX4KE8000 = 0x00080078, + HV_X64_REGISTER_MSR_MTRR_FIX4KF0000 = 0x00080079, + HV_X64_REGISTER_MSR_MTRR_FIX4KF8000 = 0x0008007A, + + HV_X64_REGISTER_TSC_AUX = 0x0008007B, + HV_X64_REGISTER_BNDCFGS = 0x0008007C, + HV_X64_REGISTER_DEBUG_CTL = 0x0008007D, + + /* Available */ + + HV_X64_REGISTER_SPEC_CTRL = 0x00080084, + HV_X64_REGISTER_TSC_ADJUST = 0x00080096, + + /* Other MSRs */ + HV_X64_REGISTER_MSR_IA32_MISC_ENABLE = 0x000800A0, + + /* Misc */ + HV_REGISTER_GUEST_OS_ID = 0x00090002, + HV_REGISTER_REFERENCE_TSC = 0x00090017, + + /* Hypervisor-defined Registers (Synic) */ + HV_REGISTER_SINT0 = 0x000A0000, + HV_REGISTER_SINT1 = 0x000A0001, + HV_REGISTER_SINT2 = 0x000A0002, + HV_REGISTER_SINT3 = 0x000A0003, + HV_REGISTER_SINT4 = 0x000A0004, + HV_REGISTER_SINT5 = 0x000A0005, + HV_REGISTER_SINT6 = 0x000A0006, + HV_REGISTER_SINT7 = 0x000A0007, + HV_REGISTER_SINT8 = 0x000A0008, + HV_REGISTER_SINT9 = 0x000A0009, + HV_REGISTER_SINT10 = 0x000A000A, + HV_REGISTER_SINT11 = 0x000A000B, + HV_REGISTER_SINT12 = 0x000A000C, + HV_REGISTER_SINT13 = 0x000A000D, + HV_REGISTER_SINT14 = 0x000A000E, + HV_REGISTER_SINT15 = 0x000A000F, + HV_REGISTER_SCONTROL = 0x000A0010, + HV_REGISTER_SVERSION = 0x000A0011, + HV_REGISTER_SIEFP = 0x000A0012, + HV_REGISTER_SIMP = 0x000A0013, + HV_REGISTER_EOM = 0x000A0014, + HV_REGISTER_SIRBP = 0x000A0015, +} hv_register_name; + +enum hv_intercept_type { + HV_INTERCEPT_TYPE_X64_IO_PORT = 0X00000000, + HV_INTERCEPT_TYPE_X64_MSR = 0X00000001, + HV_INTERCEPT_TYPE_X64_CPUID = 0X00000002, + HV_INTERCEPT_TYPE_EXCEPTION = 0X00000003, + + /* Used to be HV_INTERCEPT_TYPE_REGISTER */ + HV_INTERCEPT_TYPE_RESERVED0 = 0X00000004, + HV_INTERCEPT_TYPE_MMIO = 0X00000005, + HV_INTERCEPT_TYPE_X64_GLOBAL_CPUID = 0X00000006, + HV_INTERCEPT_TYPE_X64_APIC_SMI = 0X00000007, + HV_INTERCEPT_TYPE_HYPERCALL = 0X00000008, + + HV_INTERCEPT_TYPE_X64_APIC_INIT_SIPI = 0X00000009, + HV_INTERCEPT_MC_UPDATE_PATCH_LEVEL_MSR_READ = 0X0000000A, + + HV_INTERCEPT_TYPE_X64_APIC_WRITE = 0X0000000B, + HV_INTERCEPT_TYPE_X64_MSR_INDEX = 0X0000000C, + HV_INTERCEPT_TYPE_MAX, + HV_INTERCEPT_TYPE_INVALID = 0XFFFFFFFF, +}; + +struct hv_u128 { + uint64_t low_part; + uint64_t high_part; +}; + +union hv_x64_xmm_control_status_register { + struct hv_u128 as_uint128; + struct { + union { + /* long mode */ + uint64_t last_fp_rdp; + /* 32 bit mode */ + struct { + uint32_t last_fp_dp; + uint16_t last_fp_ds; + uint16_t padding; + }; + }; + uint32_t xmm_status_control; + uint32_t xmm_status_control_mask; + }; +}; + +union hv_x64_fp_register { + struct hv_u128 as_uint128; + struct { + uint64_t mantissa; + uint64_t biased_exponent:15; + uint64_t sign:1; + uint64_t reserved:48; + }; +}; + +union hv_x64_pending_exception_event { + uint64_t as_uint64[2]; + struct { + uint32_t event_pending:1; + uint32_t event_type:3; + uint32_t reserved0:4; + uint32_t deliver_error_code:1; + uint32_t reserved1:7; + uint32_t vector:16; + uint32_t error_code; + uint64_t exception_parameter; + }; +}; + +union hv_x64_pending_virtualization_fault_event { + uint64_t as_uint64[2]; + struct { + uint32_t event_pending:1; + uint32_t event_type:3; + uint32_t reserved0:4; + uint32_t reserved1:8; + uint32_t parameter0:16; + uint32_t code; + uint64_t parameter1; + }; +}; + +union hv_x64_pending_interruption_register { + uint64_t as_uint64; + struct { + uint32_t interruption_pending:1; + uint32_t interruption_type:3; + uint32_t deliver_error_code:1; + uint32_t instruction_length:4; + uint32_t nested_event:1; + uint32_t reserved:6; + uint32_t interruption_vector:16; + uint32_t error_code; + }; +}; + +union hv_x64_register_sev_control { + uint64_t as_uint64; + struct { + uint64_t enable_encrypted_state:1; + uint64_t reserved_z:11; + uint64_t vmsa_gpa_page_number:52; + }; +}; + +union hv_x64_msr_npiep_config_contents { + uint64_t as_uint64; + struct { + /* + * These bits enable instruction execution prevention for + * specific instructions. + */ + uint64_t prevents_gdt:1; + uint64_t prevents_idt:1; + uint64_t prevents_ldt:1; + uint64_t prevents_tr:1; + + /* The reserved bits must always be 0. */ + uint64_t reserved:60; + }; +}; + +typedef struct hv_x64_segment_register { + uint64_t base; + uint32_t limit; + uint16_t selector; + union { + struct { + uint16_t segment_type:4; + uint16_t non_system_segment:1; + uint16_t descriptor_privilege_level:2; + uint16_t present:1; + uint16_t reserved:4; + uint16_t available:1; + uint16_t _long:1; + uint16_t _default:1; + uint16_t granularity:1; + }; + uint16_t attributes; + }; +} hv_x64_segment_register; + +typedef struct hv_x64_table_register { + uint16_t pad[3]; + uint16_t limit; + uint64_t base; +} hv_x64_table_register; + +union hv_x64_fp_control_status_register { + struct hv_u128 as_uint128; + struct { + uint16_t fp_control; + uint16_t fp_status; + uint8_t fp_tag; + uint8_t reserved; + uint16_t last_fp_op; + union { + /* long mode */ + uint64_t last_fp_rip; + /* 32 bit mode */ + struct { + uint32_t last_fp_eip; + uint16_t last_fp_cs; + uint16_t padding; + }; + }; + }; +}; + +/* General Hypervisor Register Content Definitions */ + +union hv_explicit_suspend_register { + uint64_t as_uint64; + struct { + uint64_t suspended:1; + uint64_t reserved:63; + }; +}; + +union hv_internal_activity_register { + uint64_t as_uint64; + + struct { + uint64_t startup_suspend:1; + uint64_t halt_suspend:1; + uint64_t idle_suspend:1; + uint64_t rsvd_z:61; + }; +}; + +union hv_x64_interrupt_state_register { + uint64_t as_uint64; + struct { + uint64_t interrupt_shadow:1; + uint64_t nmi_masked:1; + uint64_t reserved:62; + }; +}; + +union hv_intercept_suspend_register { + uint64_t as_uint64; + struct { + uint64_t suspended:1; + uint64_t reserved:63; + }; +}; + +typedef union hv_register_value { + struct hv_u128 reg128; + uint64_t reg64; + uint32_t reg32; + uint16_t reg16; + uint8_t reg8; + union hv_x64_fp_register fp; + union hv_x64_fp_control_status_register fp_control_status; + union hv_x64_xmm_control_status_register xmm_control_status; + struct hv_x64_segment_register segment; + struct hv_x64_table_register table; + union hv_explicit_suspend_register explicit_suspend; + union hv_intercept_suspend_register intercept_suspend; + union hv_internal_activity_register internal_activity; + union hv_x64_interrupt_state_register interrupt_state; + union hv_x64_pending_interruption_register pending_interruption; + union hv_x64_msr_npiep_config_contents npiep_config; + union hv_x64_pending_exception_event pending_exception_event; + union hv_x64_pending_virtualization_fault_event + pending_virtualization_fault_event; + union hv_x64_register_sev_control sev_control; +} hv_register_value; + +typedef struct hv_register_assoc { + uint32_t name; /* enum hv_register_name */ + uint32_t reserved1; + uint64_t reserved2; + union hv_register_value value; +} hv_register_assoc; + +union hv_input_vtl { + uint8_t as_uint8; + struct { + uint8_t target_vtl:4; + uint8_t use_target_vtl:1; + uint8_t reserved_z:3; + }; +}; + +typedef struct hv_input_get_vp_registers { + uint64_t partition_id; + uint32_t vp_index; + union hv_input_vtl input_vtl; + uint8_t rsvd_z8; + uint16_t rsvd_z16; + uint32_t names[]; +} hv_input_get_vp_registers; + +typedef struct hv_input_set_vp_registers { + uint64_t partition_id; + uint32_t vp_index; + union hv_input_vtl input_vtl; + uint8_t rsvd_z8; + uint16_t rsvd_z16; + struct hv_register_assoc elements[]; +} hv_input_set_vp_registers; + +#define MSHV_VP_MAX_REGISTERS 128 + +struct mshv_vp_registers { + int count; /* at most MSHV_VP_MAX_REGISTERS */ + struct hv_register_assoc *regs; +}; + +union hv_interrupt_control { + uint64_t as_uint64; + struct { + uint32_t interrupt_type; /* enum hv_interrupt type */ + uint32_t level_triggered:1; + uint32_t logical_dest_mode:1; + uint32_t rsvd:30; + }; +}; + +struct hv_input_assert_virtual_interrupt { + uint64_t partition_id; + union hv_interrupt_control control; + uint64_t dest_addr; /* cpu's apic id */ + uint32_t vector; + uint8_t target_vtl; + uint8_t rsvd_z0; + uint16_t rsvd_z1; +}; + +/* /dev/mshv */ +#define MSHV_CREATE_PARTITION _IOW(MSHV_IOCTL, 0x00, struct mshv_create_partition) +#define MSHV_CREATE_VP _IOW(MSHV_IOCTL, 0x01, struct mshv_create_vp) + +/* Partition fds created with MSHV_CREATE_PARTITION */ +#define MSHV_INITIALIZE_PARTITION _IO(MSHV_IOCTL, 0x00) +#define MSHV_SET_GUEST_MEMORY _IOW(MSHV_IOCTL, 0x02, struct mshv_user_mem_region) +#define MSHV_IRQFD _IOW(MSHV_IOCTL, 0x03, struct mshv_user_irqfd) +#define MSHV_IOEVENTFD _IOW(MSHV_IOCTL, 0x04, struct mshv_user_ioeventfd) +#define MSHV_SET_MSI_ROUTING _IOW(MSHV_IOCTL, 0x05, struct mshv_user_irq_table) + +/* + ******************************** + * VP APIs for child partitions * + ******************************** + */ + +struct hv_local_interrupt_controller_state { + /* HV_X64_INTERRUPT_CONTROLLER_STATE */ + uint32_t apic_id; + uint32_t apic_version; + uint32_t apic_ldr; + uint32_t apic_dfr; + uint32_t apic_spurious; + uint32_t apic_isr[8]; + uint32_t apic_tmr[8]; + uint32_t apic_irr[8]; + uint32_t apic_esr; + uint32_t apic_icr_high; + uint32_t apic_icr_low; + uint32_t apic_lvt_timer; + uint32_t apic_lvt_thermal; + uint32_t apic_lvt_perfmon; + uint32_t apic_lvt_lint0; + uint32_t apic_lvt_lint1; + uint32_t apic_lvt_error; + uint32_t apic_lvt_cmci; + uint32_t apic_error_status; + uint32_t apic_initial_count; + uint32_t apic_counter_value; + uint32_t apic_divide_configuration; + uint32_t apic_remote_read; +}; + +/* Generic hypercall */ +#define MSHV_ROOT_HVCALL _IOWR(MSHV_IOCTL, 0x07, struct mshv_root_hvcall) + +/* From hvgdk_mini.h */ + +#define HV_X64_MSR_GUEST_OS_ID 0x40000000 +#define HV_X64_MSR_SINT0 0x40000090 +#define HV_X64_MSR_SINT1 0x40000091 +#define HV_X64_MSR_SINT2 0x40000092 +#define HV_X64_MSR_SINT3 0x40000093 +#define HV_X64_MSR_SINT4 0x40000094 +#define HV_X64_MSR_SINT5 0x40000095 +#define HV_X64_MSR_SINT6 0x40000096 +#define HV_X64_MSR_SINT7 0x40000097 +#define HV_X64_MSR_SINT8 0x40000098 +#define HV_X64_MSR_SINT9 0x40000099 +#define HV_X64_MSR_SINT10 0x4000009A +#define HV_X64_MSR_SINT11 0x4000009B +#define HV_X64_MSR_SINT12 0x4000009C +#define HV_X64_MSR_SINT13 0x4000009D +#define HV_X64_MSR_SINT14 0x4000009E +#define HV_X64_MSR_SINT15 0x4000009F +#define HV_X64_MSR_SCONTROL 0x40000080 +#define HV_X64_MSR_SIEFP 0x40000082 +#define HV_X64_MSR_SIMP 0x40000083 +#define HV_X64_MSR_REFERENCE_TSC 0x40000021 +#define HV_X64_MSR_EOM 0x40000084 + +/* Define port identifier type. */ +union hv_port_id { + uint32_t asuint32_t; + struct { + uint32_t id:24; + uint32_t reserved:8; + }; +}; + +#define HV_MESSAGE_SIZE (256) +#define HV_MESSAGE_PAYLOAD_BYTE_COUNT (240) +#define HV_MESSAGE_PAYLOAD_QWORD_COUNT (30) + +/* Define hypervisor message types. */ +enum hv_message_type { + HVMSG_NONE = 0x00000000, + + /* Memory access messages. */ + HVMSG_UNMAPPED_GPA = 0x80000000, + HVMSG_GPA_INTERCEPT = 0x80000001, + HVMSG_UNACCEPTED_GPA = 0x80000003, + HVMSG_GPA_ATTRIBUTE_INTERCEPT = 0x80000004, + + /* Timer notification messages. */ + HVMSG_TIMER_EXPIRED = 0x80000010, + + /* Error messages. */ + HVMSG_INVALID_VP_REGISTER_VALUE = 0x80000020, + HVMSG_UNRECOVERABLE_EXCEPTION = 0x80000021, + HVMSG_UNSUPPORTED_FEATURE = 0x80000022, + + /* + * Opaque intercept message. The original intercept message is only + * accessible from the mapped intercept message page. + */ + HVMSG_OPAQUE_INTERCEPT = 0x8000003F, + + /* Trace buffer complete messages. */ + HVMSG_EVENTLOG_BUFFERCOMPLETE = 0x80000040, + + /* Hypercall intercept */ + HVMSG_HYPERCALL_INTERCEPT = 0x80000050, + + /* SynIC intercepts */ + HVMSG_SYNIC_EVENT_INTERCEPT = 0x80000060, + HVMSG_SYNIC_SINT_INTERCEPT = 0x80000061, + HVMSG_SYNIC_SINT_DELIVERABLE = 0x80000062, + + /* Async call completion intercept */ + HVMSG_ASYNC_CALL_COMPLETION = 0x80000070, + + /* Root scheduler messages */ + HVMSG_SCHEDULER_VP_SIGNAL_BITSE = 0x80000100, + HVMSG_SCHEDULER_VP_SIGNAL_PAIR = 0x80000101, + + /* Platform-specific processor intercept messages. */ + HVMSG_X64_IO_PORT_INTERCEPT = 0x80010000, + HVMSG_X64_MSR_INTERCEPT = 0x80010001, + HVMSG_X64_CPUID_INTERCEPT = 0x80010002, + HVMSG_X64_EXCEPTION_INTERCEPT = 0x80010003, + HVMSG_X64_APIC_EOI = 0x80010004, + HVMSG_X64_LEGACY_FP_ERROR = 0x80010005, + HVMSG_X64_IOMMU_PRQ = 0x80010006, + HVMSG_X64_HALT = 0x80010007, + HVMSG_X64_INTERRUPTION_DELIVERABLE = 0x80010008, + HVMSG_X64_SIPI_INTERCEPT = 0x80010009, + HVMSG_X64_SEV_VMGEXIT_INTERCEPT = 0x80010013, +}; + +union hv_x64_vp_execution_state { + uint16_t as_uint16; + struct { + uint16_t cpl:2; + uint16_t cr0_pe:1; + uint16_t cr0_am:1; + uint16_t efer_lma:1; + uint16_t debug_active:1; + uint16_t interruption_pending:1; + uint16_t vtl:4; + uint16_t enclave_mode:1; + uint16_t interrupt_shadow:1; + uint16_t virtualization_fault_active:1; + uint16_t reserved:2; + }; +}; + +/* From openvmm::hvdef */ +enum hv_x64_intercept_access_type { + HV_X64_INTERCEPT_ACCESS_TYPE_READ = 0, + HV_X64_INTERCEPT_ACCESS_TYPE_WRITE = 1, + HV_X64_INTERCEPT_ACCESS_TYPE_EXECUTE = 2, +}; + +struct hv_x64_intercept_message_header { + uint32_t vp_index; + uint8_t instruction_length:4; + uint8_t cr8:4; /* Only set for exo partitions */ + uint8_t intercept_access_type; + union hv_x64_vp_execution_state execution_state; + struct hv_x64_segment_register cs_segment; + uint64_t rip; + uint64_t rflags; +}; + +union hv_x64_io_port_access_info { + uint8_t as_uint8; + struct { + uint8_t access_size:3; + uint8_t string_op:1; + uint8_t rep_prefix:1; + uint8_t reserved:3; + }; +}; + +typedef struct hv_x64_io_port_intercept_message { + struct hv_x64_intercept_message_header header; + uint16_t port_number; + union hv_x64_io_port_access_info access_info; + uint8_t instruction_byte_count; + uint32_t reserved; + uint64_t rax; + uint8_t instruction_bytes[16]; + struct hv_x64_segment_register ds_segment; + struct hv_x64_segment_register es_segment; + uint64_t rcx; + uint64_t rsi; + uint64_t rdi; +} hv_x64_io_port_intercept_message; + +union hv_x64_memory_access_info { + uint8_t as_uint8; + struct { + uint8_t gva_valid:1; + uint8_t gva_gpa_valid:1; + uint8_t hypercall_output_pending:1; + uint8_t tlb_locked_no_overlay:1; + uint8_t reserved:4; + }; +}; + +struct hv_x64_memory_intercept_message { + struct hv_x64_intercept_message_header header; + uint32_t cache_type; /* enum hv_cache_type */ + uint8_t instruction_byte_count; + union hv_x64_memory_access_info memory_access_info; + uint8_t tpr_priority; + uint8_t reserved1; + uint64_t guest_virtual_address; + uint64_t guest_physical_address; + uint8_t instruction_bytes[16]; +}; + +union hv_message_flags { + uint8_t asu8; + struct { + uint8_t msg_pending:1; + uint8_t reserved:7; + }; +}; + +struct hv_message_header { + uint32_t message_type; + uint8_t payload_size; + union hv_message_flags message_flags; + uint8_t reserved[2]; + union { + uint64_t sender; + union hv_port_id port; + }; +}; + +struct hv_message { + struct hv_message_header header; + union { + uint64_t payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT]; + } u; +}; + +/* From github.com/rust-vmm/mshv-bindings/src/x86_64/regs.rs */ + +struct hv_cpuid_entry { + uint32_t function; + uint32_t index; + uint32_t flags; + uint32_t eax; + uint32_t ebx; + uint32_t ecx; + uint32_t edx; + uint32_t padding[3]; +}; + +struct hv_cpuid { + uint32_t nent; + uint32_t padding; + struct hv_cpuid_entry entries[0]; +}; + +#define IA32_MSR_TSC 0x00000010 +#define IA32_MSR_EFER 0xC0000080 +#define IA32_MSR_KERNEL_GS_BASE 0xC0000102 +#define IA32_MSR_APIC_BASE 0x0000001B +#define IA32_MSR_PAT 0x0277 +#define IA32_MSR_SYSENTER_CS 0x00000174 +#define IA32_MSR_SYSENTER_ESP 0x00000175 +#define IA32_MSR_SYSENTER_EIP 0x00000176 +#define IA32_MSR_STAR 0xC0000081 +#define IA32_MSR_LSTAR 0xC0000082 +#define IA32_MSR_CSTAR 0xC0000083 +#define IA32_MSR_SFMASK 0xC0000084 + +#define IA32_MSR_MTRR_CAP 0x00FE +#define IA32_MSR_MTRR_DEF_TYPE 0x02FF +#define IA32_MSR_MTRR_PHYSBASE0 0x0200 +#define IA32_MSR_MTRR_PHYSMASK0 0x0201 +#define IA32_MSR_MTRR_PHYSBASE1 0x0202 +#define IA32_MSR_MTRR_PHYSMASK1 0x0203 +#define IA32_MSR_MTRR_PHYSBASE2 0x0204 +#define IA32_MSR_MTRR_PHYSMASK2 0x0205 +#define IA32_MSR_MTRR_PHYSBASE3 0x0206 +#define IA32_MSR_MTRR_PHYSMASK3 0x0207 +#define IA32_MSR_MTRR_PHYSBASE4 0x0208 +#define IA32_MSR_MTRR_PHYSMASK4 0x0209 +#define IA32_MSR_MTRR_PHYSBASE5 0x020A +#define IA32_MSR_MTRR_PHYSMASK5 0x020B +#define IA32_MSR_MTRR_PHYSBASE6 0x020C +#define IA32_MSR_MTRR_PHYSMASK6 0x020D +#define IA32_MSR_MTRR_PHYSBASE7 0x020E +#define IA32_MSR_MTRR_PHYSMASK7 0x020F + +#define IA32_MSR_MTRR_FIX64K_00000 0x0250 +#define IA32_MSR_MTRR_FIX16K_80000 0x0258 +#define IA32_MSR_MTRR_FIX16K_A0000 0x0259 +#define IA32_MSR_MTRR_FIX4K_C0000 0x0268 +#define IA32_MSR_MTRR_FIX4K_C8000 0x0269 +#define IA32_MSR_MTRR_FIX4K_D0000 0x026A +#define IA32_MSR_MTRR_FIX4K_D8000 0x026B +#define IA32_MSR_MTRR_FIX4K_E0000 0x026C +#define IA32_MSR_MTRR_FIX4K_E8000 0x026D +#define IA32_MSR_MTRR_FIX4K_F0000 0x026E +#define IA32_MSR_MTRR_FIX4K_F8000 0x026F + +#define IA32_MSR_TSC_AUX 0xC0000103 +#define IA32_MSR_BNDCFGS 0x00000d90 +#define IA32_MSR_DEBUG_CTL 0x1D9 +#define IA32_MSR_SPEC_CTRL 0x00000048 +#define IA32_MSR_TSC_ADJUST 0x0000003b + +#define IA32_MSR_MISC_ENABLE 0x000001a0 + +#define HV_TRANSLATE_GVA_VALIDATE_READ (0x0001) +#define HV_TRANSLATE_GVA_VALIDATE_WRITE (0x0002) +#define HV_TRANSLATE_GVA_VALIDATE_EXECUTE (0x0004) + +#define HV_HYP_PAGE_SHIFT 12 +#define HV_HYP_PAGE_SIZE BIT(HV_HYP_PAGE_SHIFT) +#define HV_HYP_PAGE_MASK (~(HV_HYP_PAGE_SIZE - 1)) + +#define HVCALL_GET_PARTITION_PROPERTY 0x0044 +#define HVCALL_SET_PARTITION_PROPERTY 0x0045 +#define HVCALL_GET_VP_REGISTERS 0x0050 +#define HVCALL_SET_VP_REGISTERS 0x0051 +#define HVCALL_TRANSLATE_VIRTUAL_ADDRESS 0x0052 +#define HVCALL_REGISTER_INTERCEPT_RESULT 0x0091 +#define HVCALL_ASSERT_VIRTUAL_INTERRUPT 0x0094 + +#endif /* HW_HYPERV_HVGDK_MINI_H */ diff --git a/include/hw/hyperv/hvhdk.h b/include/hw/hyperv/hvhdk.h new file mode 100644 index 0000000..866c821 --- /dev/null +++ b/include/hw/hyperv/hvhdk.h @@ -0,0 +1,249 @@ +/* + * Type definitions for the mshv host. + * + * Copyright Microsoft, Corp. 2025 + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_HYPERV_HVHDK_H +#define HW_HYPERV_HVHDK_H + +#define HV_PARTITION_SYNTHETIC_PROCESSOR_FEATURES_BANKS 1 + +struct hv_input_set_partition_property { + uint64_t partition_id; + uint32_t property_code; /* enum hv_partition_property_code */ + uint32_t padding; + uint64_t property_value; +}; + +union hv_partition_synthetic_processor_features { + uint64_t as_uint64[HV_PARTITION_SYNTHETIC_PROCESSOR_FEATURES_BANKS]; + + struct { + /* + * Report a hypervisor is present. CPUID leaves + * 0x40000000 and 0x40000001 are supported. + */ + uint64_t hypervisor_present:1; + + /* + * Features associated with HV#1: + */ + + /* Report support for Hv1 (CPUID leaves 0x40000000 - 0x40000006). */ + uint64_t hv1:1; + + /* + * Access to HV_X64_MSR_VP_RUNTIME. + * Corresponds to access_vp_run_time_reg privilege. + */ + uint64_t access_vp_run_time_reg:1; + + /* + * Access to HV_X64_MSR_TIME_REF_COUNT. + * Corresponds to access_partition_reference_counter privilege. + */ + uint64_t access_partition_reference_counter:1; + + /* + * Access to SINT-related registers (HV_X64_MSR_SCONTROL through + * HV_X64_MSR_EOM and HV_X64_MSR_SINT0 through HV_X64_MSR_SINT15). + * Corresponds to access_synic_regs privilege. + */ + uint64_t access_synic_regs:1; + + /* + * Access to synthetic timers and associated MSRs + * (HV_X64_MSR_STIMER0_CONFIG through HV_X64_MSR_STIMER3_COUNT). + * Corresponds to access_synthetic_timer_regs privilege. + */ + uint64_t access_synthetic_timer_regs:1; + + /* + * Access to APIC MSRs (HV_X64_MSR_EOI, HV_X64_MSR_ICR and + * HV_X64_MSR_TPR) as well as the VP assist page. + * Corresponds to access_intr_ctrl_regs privilege. + */ + uint64_t access_intr_ctrl_regs:1; + + /* + * Access to registers associated with hypercalls + * (HV_X64_MSR_GUEST_OS_ID and HV_X64_MSR_HYPERCALL). + * Corresponds to access_hypercall_msrs privilege. + */ + uint64_t access_hypercall_regs:1; + + /* VP index can be queried. corresponds to access_vp_index privilege. */ + uint64_t access_vp_index:1; + + /* + * Access to the reference TSC. Corresponds to + * access_partition_reference_tsc privilege. + */ + uint64_t access_partition_reference_tsc:1; + + /* + * Partition has access to the guest idle reg. Corresponds to + * access_guest_idle_reg privilege. + */ + uint64_t access_guest_idle_reg:1; + + /* + * Partition has access to frequency regs. corresponds to + * access_frequency_regs privilege. + */ + uint64_t access_frequency_regs:1; + + uint64_t reserved_z12:1; /* Reserved for access_reenlightenment_controls */ + uint64_t reserved_z13:1; /* Reserved for access_root_scheduler_reg */ + uint64_t reserved_z14:1; /* Reserved for access_tsc_invariant_controls */ + + /* + * Extended GVA ranges for HvCallFlushVirtualAddressList hypercall. + * Corresponds to privilege. + */ + uint64_t enable_extended_gva_ranges_for_flush_virtual_address_list:1; + + uint64_t reserved_z16:1; /* Reserved for access_vsm. */ + uint64_t reserved_z17:1; /* Reserved for access_vp_registers. */ + + /* Use fast hypercall output. Corresponds to privilege. */ + uint64_t fast_hypercall_output:1; + + uint64_t reserved_z19:1; /* Reserved for enable_extended_hypercalls. */ + + /* + * HvStartVirtualProcessor can be used to start virtual processors. + * Corresponds to privilege. + */ + uint64_t start_virtual_processor:1; + + uint64_t reserved_z21:1; /* Reserved for Isolation. */ + + /* Synthetic timers in direct mode. */ + uint64_t direct_synthetic_timers:1; + + uint64_t reserved_z23:1; /* Reserved for synthetic time unhalted timer */ + + /* Use extended processor masks. */ + uint64_t extended_processor_masks:1; + + /* + * HvCallFlushVirtualAddressSpace / HvCallFlushVirtualAddressList are + * supported. + */ + uint64_t tb_flush_hypercalls:1; + + /* HvCallSendSyntheticClusterIpi is supported. */ + uint64_t synthetic_cluster_ipi:1; + + /* HvCallNotifyLongSpinWait is supported. */ + uint64_t notify_long_spin_wait:1; + + /* HvCallQueryNumaDistance is supported. */ + uint64_t query_numa_distance:1; + + /* HvCallSignalEvent is supported. Corresponds to privilege. */ + uint64_t signal_events:1; + + /* HvCallRetargetDeviceInterrupt is supported. */ + uint64_t retarget_device_interrupt:1; + + /* HvCallRestorePartitionTime is supported. */ + uint64_t restore_time:1; + + /* EnlightenedVmcs nested enlightenment is supported. */ + uint64_t enlightened_vmcs:1; + + uint64_t reserved:30; + }; +}; + +enum hv_translate_gva_result_code { + HV_TRANSLATE_GVA_SUCCESS = 0, + + /* Translation failures. */ + HV_TRANSLATE_GVA_PAGE_NOT_PRESENT = 1, + HV_TRANSLATE_GVA_PRIVILEGE_VIOLATION = 2, + HV_TRANSLATE_GVA_INVALIDE_PAGE_TABLE_FLAGS = 3, + + /* GPA access failures. */ + HV_TRANSLATE_GVA_GPA_UNMAPPED = 4, + HV_TRANSLATE_GVA_GPA_NO_READ_ACCESS = 5, + HV_TRANSLATE_GVA_GPA_NO_WRITE_ACCESS = 6, + HV_TRANSLATE_GVA_GPA_ILLEGAL_OVERLAY_ACCESS = 7, + + /* + * Intercept for memory access by either + * - a higher VTL + * - a nested hypervisor (due to a violation of the nested page table) + */ + HV_TRANSLATE_GVA_INTERCEPT = 8, + + HV_TRANSLATE_GVA_GPA_UNACCEPTED = 9, +}; + +union hv_translate_gva_result { + uint64_t as_uint64; + struct { + uint32_t result_code; /* enum hv_translate_hva_result_code */ + uint32_t cache_type:8; + uint32_t overlay_page:1; + uint32_t reserved:23; + }; +}; + +typedef struct hv_input_translate_virtual_address { + uint64_t partition_id; + uint32_t vp_index; + uint32_t padding; + uint64_t control_flags; + uint64_t gva_page; +} hv_input_translate_virtual_address; + +typedef struct hv_output_translate_virtual_address { + union hv_translate_gva_result translation_result; + uint64_t gpa_page; +} hv_output_translate_virtual_address; + +typedef struct hv_register_x64_cpuid_result_parameters { + struct { + uint32_t eax; + uint32_t ecx; + uint8_t subleaf_specific; + uint8_t always_override; + uint16_t padding; + } input; + struct { + uint32_t eax; + uint32_t eax_mask; + uint32_t ebx; + uint32_t ebx_mask; + uint32_t ecx; + uint32_t ecx_mask; + uint32_t edx; + uint32_t edx_mask; + } result; +} hv_register_x64_cpuid_result_parameters; + +typedef struct hv_register_x64_msr_result_parameters { + uint32_t msr_index; + uint32_t access_type; + uint32_t action; /* enum hv_unimplemented_msr_action */ +} hv_register_x64_msr_result_parameters; + +union hv_register_intercept_result_parameters { + struct hv_register_x64_cpuid_result_parameters cpuid; + struct hv_register_x64_msr_result_parameters msr; +}; + +typedef struct hv_input_register_intercept_result { + uint64_t partition_id; + uint32_t vp_index; + uint32_t intercept_type; /* enum hv_intercept_type */ + union hv_register_intercept_result_parameters parameters; +} hv_input_register_intercept_result; + +#endif /* HW_HYPERV_HVHDK_H */ diff --git a/include/hw/hyperv/hvhdk_mini.h b/include/hw/hyperv/hvhdk_mini.h new file mode 100644 index 0000000..9c2f3cf --- /dev/null +++ b/include/hw/hyperv/hvhdk_mini.h @@ -0,0 +1,102 @@ +/* + * Type definitions for the mshv host interface. + * + * Copyright Microsoft, Corp. 2025 + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_HYPERV_HVHDK_MINI_H +#define HW_HYPERV_HVHDK_MINI_H + +#define HVHVK_MINI_VERSION (25294) + +/* Each generic set contains 64 elements */ +#define HV_GENERIC_SET_SHIFT (6) +#define HV_GENERIC_SET_MASK (63) + +enum hv_generic_set_format { + HV_GENERIC_SET_SPARSE_4K, + HV_GENERIC_SET_ALL, +}; + +enum hv_partition_property_code { + /* Privilege properties */ + HV_PARTITION_PROPERTY_PRIVILEGE_FLAGS = 0x00010000, + HV_PARTITION_PROPERTY_SYNTHETIC_PROC_FEATURES = 0x00010001, + + /* Scheduling properties */ + HV_PARTITION_PROPERTY_SUSPEND = 0x00020000, + HV_PARTITION_PROPERTY_CPU_RESERVE = 0x00020001, + HV_PARTITION_PROPERTY_CPU_CAP = 0x00020002, + HV_PARTITION_PROPERTY_CPU_WEIGHT = 0x00020003, + HV_PARTITION_PROPERTY_CPU_GROUP_ID = 0x00020004, + + /* Time properties */ + HV_PARTITION_PROPERTY_TIME_FREEZE = 0x00030003, + HV_PARTITION_PROPERTY_REFERENCE_TIME = 0x00030005, + + /* Debugging properties */ + HV_PARTITION_PROPERTY_DEBUG_CHANNEL_ID = 0x00040000, + + /* Resource properties */ + HV_PARTITION_PROPERTY_VIRTUAL_TLB_PAGE_COUNT = 0x00050000, + HV_PARTITION_PROPERTY_VSM_CONFIG = 0x00050001, + HV_PARTITION_PROPERTY_ZERO_MEMORY_ON_RESET = 0x00050002, + HV_PARTITION_PROPERTY_PROCESSORS_PER_SOCKET = 0x00050003, + HV_PARTITION_PROPERTY_NESTED_TLB_SIZE = 0x00050004, + HV_PARTITION_PROPERTY_GPA_PAGE_ACCESS_TRACKING = 0x00050005, + HV_PARTITION_PROPERTY_VSM_PERMISSIONS_DIRTY_SINCE_LAST_QUERY = 0x00050006, + HV_PARTITION_PROPERTY_SGX_LAUNCH_CONTROL_CONFIG = 0x00050007, + HV_PARTITION_PROPERTY_DEFAULT_SGX_LAUNCH_CONTROL0 = 0x00050008, + HV_PARTITION_PROPERTY_DEFAULT_SGX_LAUNCH_CONTROL1 = 0x00050009, + HV_PARTITION_PROPERTY_DEFAULT_SGX_LAUNCH_CONTROL2 = 0x0005000a, + HV_PARTITION_PROPERTY_DEFAULT_SGX_LAUNCH_CONTROL3 = 0x0005000b, + HV_PARTITION_PROPERTY_ISOLATION_STATE = 0x0005000c, + HV_PARTITION_PROPERTY_ISOLATION_CONTROL = 0x0005000d, + HV_PARTITION_PROPERTY_ALLOCATION_ID = 0x0005000e, + HV_PARTITION_PROPERTY_MONITORING_ID = 0x0005000f, + HV_PARTITION_PROPERTY_IMPLEMENTED_PHYSICAL_ADDRESS_BITS = 0x00050010, + HV_PARTITION_PROPERTY_NON_ARCHITECTURAL_CORE_SHARING = 0x00050011, + HV_PARTITION_PROPERTY_HYPERCALL_DOORBELL_PAGE = 0x00050012, + HV_PARTITION_PROPERTY_ISOLATION_POLICY = 0x00050014, + HV_PARTITION_PROPERTY_UNIMPLEMENTED_MSR_ACTION = 0x00050017, + HV_PARTITION_PROPERTY_SEV_VMGEXIT_OFFLOADS = 0x00050022, + + /* Compatibility properties */ + HV_PARTITION_PROPERTY_PROCESSOR_VENDOR = 0x00060000, + HV_PARTITION_PROPERTY_PROCESSOR_FEATURES_DEPRECATED = 0x00060001, + HV_PARTITION_PROPERTY_PROCESSOR_XSAVE_FEATURES = 0x00060002, + HV_PARTITION_PROPERTY_PROCESSOR_CL_FLUSH_SIZE = 0x00060003, + HV_PARTITION_PROPERTY_ENLIGHTENMENT_MODIFICATIONS = 0x00060004, + HV_PARTITION_PROPERTY_COMPATIBILITY_VERSION = 0x00060005, + HV_PARTITION_PROPERTY_PHYSICAL_ADDRESS_WIDTH = 0x00060006, + HV_PARTITION_PROPERTY_XSAVE_STATES = 0x00060007, + HV_PARTITION_PROPERTY_MAX_XSAVE_DATA_SIZE = 0x00060008, + HV_PARTITION_PROPERTY_PROCESSOR_CLOCK_FREQUENCY = 0x00060009, + HV_PARTITION_PROPERTY_PROCESSOR_FEATURES0 = 0x0006000a, + HV_PARTITION_PROPERTY_PROCESSOR_FEATURES1 = 0x0006000b, + + /* Guest software properties */ + HV_PARTITION_PROPERTY_GUEST_OS_ID = 0x00070000, + + /* Nested virtualization properties */ + HV_PARTITION_PROPERTY_PROCESSOR_VIRTUALIZATION_FEATURES = 0x00080000, +}; + +/* HV Map GPA (Guest Physical Address) Flags */ +#define HV_MAP_GPA_PERMISSIONS_NONE 0x0 +#define HV_MAP_GPA_READABLE 0x1 +#define HV_MAP_GPA_WRITABLE 0x2 +#define HV_MAP_GPA_KERNEL_EXECUTABLE 0x4 +#define HV_MAP_GPA_USER_EXECUTABLE 0x8 +#define HV_MAP_GPA_EXECUTABLE 0xC +#define HV_MAP_GPA_PERMISSIONS_MASK 0xF +#define HV_MAP_GPA_ADJUSTABLE 0x8000 +#define HV_MAP_GPA_NO_ACCESS 0x10000 +#define HV_MAP_GPA_NOT_CACHED 0x200000 +#define HV_MAP_GPA_LARGE_PAGE 0x80000000 + +#define HV_PFN_RNG_PAGEBITS 24 /* HV_SPA_PAGE_RANGE_ADDITIONAL_PAGES_BITS */ + +#endif /* HW_HYPERV_HVHDK_MINI_H */ diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h index 2c4c81b..2daacc1 100644 --- a/include/hw/i2c/aspeed_i2c.h +++ b/include/hw/i2c/aspeed_i2c.h @@ -14,8 +14,7 @@ * 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, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * with this program; if not, see <https://www.gnu.org/licenses/>. */ #ifndef ASPEED_I2C_H diff --git a/include/hw/i386/apic.h b/include/hw/i386/apic.h index eb606d6..6a0933f 100644 --- a/include/hw/i386/apic.h +++ b/include/hw/i386/apic.h @@ -1,28 +1,29 @@ #ifndef APIC_H #define APIC_H +typedef struct APICCommonState APICCommonState; /* apic.c */ void apic_set_max_apic_id(uint32_t max_apic_id); -int apic_accept_pic_intr(DeviceState *s); -void apic_deliver_pic_intr(DeviceState *s, int level); -void apic_deliver_nmi(DeviceState *d); -int apic_get_interrupt(DeviceState *s); -int cpu_set_apic_base(DeviceState *s, uint64_t val); -uint64_t cpu_get_apic_base(DeviceState *s); -bool cpu_is_apic_enabled(DeviceState *s); -void cpu_set_apic_tpr(DeviceState *s, uint8_t val); -uint8_t cpu_get_apic_tpr(DeviceState *s); -void apic_init_reset(DeviceState *s); -void apic_sipi(DeviceState *s); -void apic_poll_irq(DeviceState *d); -void apic_designate_bsp(DeviceState *d, bool bsp); -int apic_get_highest_priority_irr(DeviceState *dev); -int apic_msr_read(int index, uint64_t *val); -int apic_msr_write(int index, uint64_t val); -bool is_x2apic_mode(DeviceState *d); +int apic_accept_pic_intr(APICCommonState *s); +void apic_deliver_pic_intr(APICCommonState *s, int level); +void apic_deliver_nmi(APICCommonState *s); +int apic_get_interrupt(APICCommonState *s); +int cpu_set_apic_base(APICCommonState *s, uint64_t val); +uint64_t cpu_get_apic_base(APICCommonState *s); +bool cpu_is_apic_enabled(APICCommonState *s); +void cpu_set_apic_tpr(APICCommonState *s, uint8_t val); +uint8_t cpu_get_apic_tpr(APICCommonState *s); +void apic_init_reset(APICCommonState *s); +void apic_sipi(APICCommonState *s); +void apic_poll_irq(APICCommonState *s); +void apic_designate_bsp(APICCommonState *s, bool bsp); +int apic_get_highest_priority_irr(APICCommonState *s); +int apic_msr_read(APICCommonState *s, int index, uint64_t *val); +int apic_msr_write(APICCommonState *s, int index, uint64_t val); +bool is_x2apic_mode(APICCommonState *s); /* pc.c */ -DeviceState *cpu_get_current_apic(void); +APICCommonState *cpu_get_current_apic(void); #endif diff --git a/include/hw/i386/apic_internal.h b/include/hw/i386/apic_internal.h index 429278d..4a62fdc 100644 --- a/include/hw/i386/apic_internal.h +++ b/include/hw/i386/apic_internal.h @@ -22,6 +22,7 @@ #define QEMU_APIC_INTERNAL_H #include "cpu.h" +#include "hw/i386/apic.h" #include "system/memory.h" #include "qemu/timer.h" #include "target/i386/cpu-qom.h" @@ -125,8 +126,6 @@ #define VAPIC_ENABLE_BIT 0 #define VAPIC_ENABLE_MASK (1 << VAPIC_ENABLE_BIT) -typedef struct APICCommonState APICCommonState; - #define TYPE_APIC_COMMON "apic-common" typedef struct APICCommonClass APICCommonClass; DECLARE_OBJ_CHECKERS(APICCommonState, APICCommonClass, @@ -203,8 +202,8 @@ typedef struct VAPICState { extern bool apic_report_tpr_access; bool apic_next_timer(APICCommonState *s, int64_t current_time); -void apic_enable_tpr_access_reporting(DeviceState *d, bool enable); -void apic_enable_vapic(DeviceState *d, hwaddr paddr); +void apic_enable_tpr_access_reporting(APICCommonState *s, bool enable); +void apic_enable_vapic(APICCommonState *s, hwaddr paddr); void vapic_report_tpr_access(DeviceState *dev, CPUState *cpu, target_ulong ip, TPRAccess access); diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h index e95477e..ca7f7bb 100644 --- a/include/hw/i386/intel_iommu.h +++ b/include/hw/i386/intel_iommu.h @@ -95,6 +95,11 @@ struct VTDPASIDEntry { uint64_t val[8]; }; +typedef struct VTDPASIDCacheEntry { + struct VTDPASIDEntry pasid_entry; + bool valid; +} VTDPASIDCacheEntry; + struct VTDAddressSpace { PCIBus *bus; uint8_t devfn; @@ -107,9 +112,11 @@ struct VTDAddressSpace { MemoryRegion iommu_ir_fault; /* Interrupt region for catching fault */ IntelIOMMUState *iommu_state; VTDContextCacheEntry context_cache_entry; + VTDPASIDCacheEntry pasid_cache_entry; QLIST_ENTRY(VTDAddressSpace) next; /* Superset of notifier flags that this address space has */ IOMMUNotifierFlag notifier_flags; + IOMMUPRINotifier *pri_notifier; /* * @iova_tree traces mapped IOVA ranges. * @@ -306,7 +313,6 @@ struct IntelIOMMUState { bool buggy_eim; /* Force buggy EIM unless eim=off */ uint8_t aw_bits; /* Host/IOVA address width (in bits) */ bool dma_drain; /* Whether DMA r/w draining enabled */ - bool dma_translation; /* Whether DMA translation supported */ bool pasid; /* Whether to support PASID */ bool fs1gp; /* First Stage 1-GByte Page Support */ diff --git a/include/hw/i386/microvm.h b/include/hw/i386/microvm.h index b9ac34a..e73d1e6 100644 --- a/include/hw/i386/microvm.h +++ b/include/hw/i386/microvm.h @@ -102,8 +102,6 @@ struct MicrovmMachineState { Notifier powerdown_req; struct GPEXConfig gpex; - /* device tree */ - void *fdt; uint32_t ioapic_phandle[2]; }; diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 9563674..e83157a 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -107,7 +107,6 @@ struct PCMachineClass { /* RAM / address space compat: */ bool gigabyte_align; bool has_reserved_memory; - bool broken_reserved_end; bool enforce_amd_1tb_hole; bool isa_bios_alias; @@ -215,6 +214,9 @@ void pc_system_parse_ovmf_flash(uint8_t *flash_ptr, size_t flash_size); /* sgx.c */ void pc_machine_init_sgx_epc(PCMachineState *pcms); +extern GlobalProperty pc_compat_10_1[]; +extern const size_t pc_compat_10_1_len; + extern GlobalProperty pc_compat_10_0[]; extern const size_t pc_compat_10_0_len; @@ -299,12 +301,6 @@ extern const size_t pc_compat_2_7_len; extern GlobalProperty pc_compat_2_6[]; extern const size_t pc_compat_2_6_len; -extern GlobalProperty pc_compat_2_5[]; -extern const size_t pc_compat_2_5_len; - -extern GlobalProperty pc_compat_2_4[]; -extern const size_t pc_compat_2_4_len; - #define DEFINE_PC_MACHINE(suffix, namestr, initfn, optsfn) \ static void pc_machine_##suffix##_class_init(ObjectClass *oc, \ const void *data) \ diff --git a/include/hw/i386/tdvf.h b/include/hw/i386/tdvf.h new file mode 100644 index 0000000..e75c8d1 --- /dev/null +++ b/include/hw/i386/tdvf.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2025 Intel Corporation + * Author: Isaku Yamahata <isaku.yamahata at gmail.com> + * <isaku.yamahata at intel.com> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_I386_TDVF_H +#define HW_I386_TDVF_H + +#include "qemu/osdep.h" + +#define TDVF_SECTION_TYPE_BFV 0 +#define TDVF_SECTION_TYPE_CFV 1 +#define TDVF_SECTION_TYPE_TD_HOB 2 +#define TDVF_SECTION_TYPE_TEMP_MEM 3 + +#define TDVF_SECTION_ATTRIBUTES_MR_EXTEND (1U << 0) +#define TDVF_SECTION_ATTRIBUTES_PAGE_AUG (1U << 1) + +typedef struct TdxFirmwareEntry { + uint32_t data_offset; + uint32_t data_len; + uint64_t address; + uint64_t size; + uint32_t type; + uint32_t attributes; + + void *mem_ptr; +} TdxFirmwareEntry; + +typedef struct TdxFirmware { + void *mem_ptr; + + uint32_t nr_entries; + TdxFirmwareEntry *entries; +} TdxFirmware; + +#define for_each_tdx_fw_entry(fw, e) \ + for (e = (fw)->entries; e != (fw)->entries + (fw)->nr_entries; e++) + +int tdvf_parse_metadata(TdxFirmware *fw, void *flash_ptr, int size); + +#endif /* HW_I386_TDVF_H */ diff --git a/include/hw/i386/x86-iommu.h b/include/hw/i386/x86-iommu.h index bfd2164..e89f55a 100644 --- a/include/hw/i386/x86-iommu.h +++ b/include/hw/i386/x86-iommu.h @@ -64,6 +64,7 @@ struct X86IOMMUState { OnOffAuto intr_supported; /* Whether vIOMMU supports IR */ bool dt_supported; /* Whether vIOMMU supports DT */ bool pt_supported; /* Whether vIOMMU supports pass-through */ + bool dma_translation; /* Whether vIOMMU supports DMA translation */ QLIST_HEAD(, IEC_Notifier) iec_notifiers; /* IEC notify list */ }; diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h index 258b134..8755cad 100644 --- a/include/hw/i386/x86.h +++ b/include/hw/i386/x86.h @@ -25,15 +25,11 @@ #include "hw/intc/ioapic.h" #include "hw/isa/isa.h" #include "qom/object.h" +#include "system/igvm-cfg.h" struct X86MachineClass { - /*< private >*/ MachineClass parent; - /*< public >*/ - - /* TSC rate migration: */ - bool save_tsc_khz; /* use DMA capable linuxboot option rom */ bool fwcfg_dma_enabled; /* CPU and apic information: */ @@ -97,6 +93,8 @@ struct X86MachineState { * which means no limitation on the guest's bus locks. */ uint64_t bus_lock_ratelimit; + + IgvmCfg *igvm; }; #define X86_MACHINE_SMM "smm" diff --git a/include/hw/i386/xen_arch_hvm.h b/include/hw/i386/xen_arch_hvm.h deleted file mode 100644 index 1000f8f..0000000 --- a/include/hw/i386/xen_arch_hvm.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef HW_XEN_ARCH_I386_HVM_H -#define HW_XEN_ARCH_I386_HVM_H - -#include <xen/hvm/ioreq.h> -#include "hw/xen/xen-hvm-common.h" - -void arch_handle_ioreq(XenIOState *state, ioreq_t *req); -void arch_xen_set_memory(XenIOState *state, - MemoryRegionSection *section, - bool add); -#endif diff --git a/include/hw/input/lasips2.h b/include/hw/input/lasips2.h index 01911c5..fd74883 100644 --- a/include/hw/input/lasips2.h +++ b/include/hw/input/lasips2.h @@ -32,7 +32,8 @@ struct LASIPS2PortDeviceClass { DeviceRealize parent_realize; }; -typedef struct LASIPS2State LASIPS2State; +#define TYPE_LASIPS2 "lasips2" +OBJECT_DECLARE_SIMPLE_TYPE(LASIPS2State, LASIPS2) struct LASIPS2Port { DeviceState parent_obj; @@ -74,7 +75,4 @@ struct LASIPS2State { qemu_irq irq; }; -#define TYPE_LASIPS2 "lasips2" -OBJECT_DECLARE_SIMPLE_TYPE(LASIPS2State, LASIPS2) - #endif /* HW_INPUT_LASIPS2_H */ diff --git a/include/hw/intc/arm_gic.h b/include/hw/intc/arm_gic.h index 48f6a51..be923f7 100644 --- a/include/hw/intc/arm_gic.h +++ b/include/hw/intc/arm_gic.h @@ -27,6 +27,9 @@ * implement the security extensions * + QOM property "has-virtualization-extensions": set true if the GIC should * implement the virtualization extensions + * + QOM property "first-cpu-index": index of the first cpu attached to the + * GIC (default 0). The CPUs connected to the GIC are assumed to be + * first-cpu-index, first-cpu-index + 1, ... first-cpu-index + num-cpu - 1. * + unnamed GPIO inputs: (where P is number of SPIs, i.e. num-irq - 32) * [0..P-1] SPIs * [P..P+31] PPIs for CPU 0 diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h index 97fea41..93a3cc2 100644 --- a/include/hw/intc/arm_gic_common.h +++ b/include/hw/intc/arm_gic_common.h @@ -129,6 +129,8 @@ struct GICState { uint32_t num_lrs; uint32_t num_cpu; + /* cpu_index of the first CPU, attached to this GIC. */ + uint32_t first_cpu_index; MemoryRegion iomem; /* Distributor */ /* This is just so we can have an opaque pointer which identifies diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h index a3d6a0e..61d5191 100644 --- a/include/hw/intc/arm_gicv3_common.h +++ b/include/hw/intc/arm_gicv3_common.h @@ -27,6 +27,7 @@ #include "hw/sysbus.h" #include "hw/intc/arm_gic_common.h" #include "qom/object.h" +#include "qemu/notify.h" /* * Maximum number of possible interrupts, determined by the GIC architecture. @@ -165,6 +166,9 @@ struct GICv3CPUState { uint64_t icc_igrpen[3]; uint64_t icc_ctlr_el3; + /* For KVM, cached copy of the kernel reset value of ICC_CTLR_EL1 */ + uint64_t kvm_reset_icc_ctlr_el1; + /* Virtualization control interface */ uint64_t ich_apr[3][4]; /* ich_apr[GICV3_G1][x] never used */ uint64_t ich_hcr_el2; @@ -228,9 +232,11 @@ struct GICv3State { uint32_t *redist_region_count; /* redistributor count within each region */ uint32_t nb_redist_regions; /* number of redist regions */ + uint32_t first_cpu_idx; uint32_t num_cpu; uint32_t num_irq; uint32_t revision; + uint32_t maint_irq; bool lpi_enable; bool nmi_support; bool security_extn; @@ -270,6 +276,8 @@ struct GICv3State { GICv3CPUState *cpu; /* List of all ITSes connected to this GIC */ GPtrArray *itslist; + + NotifierWithReturn cpr_notifier; }; #define GICV3_BITMAP_ACCESSORS(BMP) \ diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h index 7dc712b..3c7b543 100644 --- a/include/hw/intc/arm_gicv3_its_common.h +++ b/include/hw/intc/arm_gicv3_its_common.h @@ -128,7 +128,7 @@ struct GICv3ITSCommonClass { * Return the ITS class name to use depending on whether KVM acceleration * and KVM CAP_SIGNAL_MSI are supported * - * Returns: class name to use or NULL + * Returns: class name to use */ const char *its_class_name(void); diff --git a/include/hw/intc/loongarch_dintc.h b/include/hw/intc/loongarch_dintc.h new file mode 100644 index 0000000..01bb1e4 --- /dev/null +++ b/include/hw/intc/loongarch_dintc.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * LoongArch direct interrupt controller definitions + * + * Copyright (C) 2025 Loongson Technology Corporation Limited + */ + +#include "qom/object.h" +#include "hw/sysbus.h" +#include "hw/loongarch/virt.h" +#include "system/memory.h" + +#define NR_VECTORS 256 + +#define TYPE_LOONGARCH_DINTC "loongarch_dintc" +OBJECT_DECLARE_TYPE(LoongArchDINTCState, LoongArchDINTCClass, LOONGARCH_DINTC) + +typedef struct DINTCCore { + CPUState *cpu; + qemu_irq parent_irq; + uint64_t arch_id; +} DINTCCore; + +struct LoongArchDINTCState { + SysBusDevice parent_obj; + MemoryRegion dintc_mmio; + DINTCCore *cpu; + uint32_t num_cpu; +}; + +struct LoongArchDINTCClass { + SysBusDeviceClass parent_class; + + DeviceRealize parent_realize; + DeviceUnrealize parent_unrealize; +}; diff --git a/include/hw/intc/loongarch_extioi.h b/include/hw/intc/loongarch_extioi.h index 4a6ae90..4795bdc 100644 --- a/include/hw/intc/loongarch_extioi.h +++ b/include/hw/intc/loongarch_extioi.h @@ -15,14 +15,18 @@ OBJECT_DECLARE_TYPE(LoongArchExtIOIState, LoongArchExtIOIClass, LOONGARCH_EXTIOI struct LoongArchExtIOIState { LoongArchExtIOICommonState parent_obj; + int dev_fd; }; struct LoongArchExtIOIClass { LoongArchExtIOICommonClass parent_class; DeviceRealize parent_realize; - DeviceUnrealize parent_unrealize; ResettablePhases parent_phases; }; +void kvm_extioi_realize(DeviceState *dev, Error **errp); +int kvm_extioi_get(void *opaque); +int kvm_extioi_put(void *opaque, int version_id); + #endif /* LOONGARCH_EXTIOI_H */ diff --git a/include/hw/intc/loongarch_extioi_common.h b/include/hw/intc/loongarch_extioi_common.h index 735bfee..1bd2bfa 100644 --- a/include/hw/intc/loongarch_extioi_common.h +++ b/include/hw/intc/loongarch_extioi_common.h @@ -10,6 +10,7 @@ #include "qom/object.h" #include "hw/sysbus.h" #include "hw/loongarch/virt.h" +#include "system/memory.h" #define LS3A_INTC_IP 8 #define EXTIOI_IRQS (256) @@ -35,7 +36,7 @@ #define EXTIOI_ISR_START (0x700 - APIC_OFFSET) #define EXTIOI_ISR_END (0x720 - APIC_OFFSET) #define EXTIOI_COREISR_START (0x800 - APIC_OFFSET) -#define EXTIOI_COREISR_END (0xB20 - APIC_OFFSET) +#define EXTIOI_COREISR_END (0x820 - APIC_OFFSET) #define EXTIOI_COREMAP_START (0xC00 - APIC_OFFSET) #define EXTIOI_COREMAP_END (0xD00 - APIC_OFFSET) #define EXTIOI_SIZE 0x800 @@ -94,6 +95,7 @@ struct LoongArchExtIOICommonClass { SysBusDeviceClass parent_class; DeviceRealize parent_realize; + DeviceUnrealize parent_unrealize; ResettablePhases parent_phases; int (*pre_save)(void *s); int (*post_load)(void *s, int version_id); diff --git a/include/hw/intc/loongarch_ipi.h b/include/hw/intc/loongarch_ipi.h index a7c6bf8..5175a6b 100644 --- a/include/hw/intc/loongarch_ipi.h +++ b/include/hw/intc/loongarch_ipi.h @@ -16,6 +16,7 @@ OBJECT_DECLARE_TYPE(LoongarchIPIState, LoongarchIPIClass, LOONGARCH_IPI) struct LoongarchIPIState { LoongsonIPICommonState parent_obj; + int dev_fd; }; struct LoongarchIPIClass { @@ -24,4 +25,8 @@ struct LoongarchIPIClass { ResettablePhases parent_phases; }; +void kvm_ipi_realize(DeviceState *dev, Error **errp); +int kvm_ipi_get(void *opaque); +int kvm_ipi_put(void *opaque, int version_id); + #endif diff --git a/include/hw/intc/loongarch_pch_msi.h b/include/hw/intc/loongarch_pch_msi.h index b8586fb..ef4ec4f 100644 --- a/include/hw/intc/loongarch_pch_msi.h +++ b/include/hw/intc/loongarch_pch_msi.h @@ -6,6 +6,7 @@ */ #include "hw/sysbus.h" +#include "system/memory.h" #define TYPE_LOONGARCH_PCH_MSI "loongarch_pch_msi" OBJECT_DECLARE_SIMPLE_TYPE(LoongArchPCHMSI, LOONGARCH_PCH_MSI) diff --git a/include/hw/intc/loongarch_pch_pic.h b/include/hw/intc/loongarch_pch_pic.h index 839a59a..a46b6f8 100644 --- a/include/hw/intc/loongarch_pch_pic.h +++ b/include/hw/intc/loongarch_pch_pic.h @@ -16,6 +16,7 @@ OBJECT_DECLARE_TYPE(LoongarchPICState, LoongarchPICClass, LOONGARCH_PIC) struct LoongarchPICState { LoongArchPICCommonState parent_obj; + int dev_fd; }; struct LoongarchPICClass { @@ -25,4 +26,8 @@ struct LoongarchPICClass { ResettablePhases parent_phases; }; +void kvm_pic_realize(DeviceState *dev, Error **errp); +int kvm_pic_get(void *opaque); +int kvm_pic_put(void *opaque, int version_id); + #endif /* HW_LOONGARCH_PCH_PIC_H */ diff --git a/include/hw/intc/loongarch_pic_common.h b/include/hw/intc/loongarch_pic_common.h index 9349a05..179361e 100644 --- a/include/hw/intc/loongarch_pic_common.h +++ b/include/hw/intc/loongarch_pic_common.h @@ -7,8 +7,9 @@ #ifndef HW_LOONGARCH_PIC_COMMON_H #define HW_LOONGARCH_PIC_COMMON_H -#include "hw/pci-host/ls7a.h" +#include "hw/loongarch/virt.h" #include "hw/sysbus.h" +#include "system/memory.h" #define PCH_PIC_INT_ID 0x00 #define PCH_PIC_INT_ID_VAL 0x7 @@ -23,6 +24,7 @@ #define PCH_PIC_ROUTE_ENTRY_END 0x13f #define PCH_PIC_HTMSI_VEC 0x200 #define PCH_PIC_HTMSI_VEC_END 0x23f +#define PCH_PIC_INT_REQUEST 0x380 #define PCH_PIC_INT_STATUS 0x3a0 #define PCH_PIC_INT_POL 0x3e0 diff --git a/include/hw/intc/loongson_ipi_common.h b/include/hw/intc/loongson_ipi_common.h index b587f9c..4fa03bc 100644 --- a/include/hw/intc/loongson_ipi_common.h +++ b/include/hw/intc/loongson_ipi_common.h @@ -11,6 +11,7 @@ #include "qom/object.h" #include "hw/sysbus.h" #include "exec/memattrs.h" +#include "system/memory.h" #define IPI_MBX_NUM 4 @@ -48,6 +49,8 @@ struct LoongsonIPICommonClass { AddressSpace *(*get_iocsr_as)(CPUState *cpu); int (*cpu_by_arch_id)(LoongsonIPICommonState *lics, int64_t id, int *index, CPUState **pcs); + int (*pre_save)(void *opaque); + int (*post_load)(void *opaque, int version_id); }; MemTxResult loongson_ipi_core_readl(void *opaque, hwaddr addr, uint64_t *data, diff --git a/include/hw/intc/riscv_aclint.h b/include/hw/intc/riscv_aclint.h index 693415e..4b7406e 100644 --- a/include/hw/intc/riscv_aclint.h +++ b/include/hw/intc/riscv_aclint.h @@ -80,4 +80,8 @@ enum { RISCV_ACLINT_SWI_SIZE = 0x4000 }; +#define VMSTATE_TIMER_PTR_VARRAY(_f, _s, _f_n) \ +VMSTATE_VARRAY_OF_POINTER_UINT32(_f, _s, _f_n, 0, vmstate_info_timer, \ + QEMUTimer *) + #endif diff --git a/include/hw/irq.h b/include/hw/irq.h index b301223..291fdd6 100644 --- a/include/hw/irq.h +++ b/include/hw/irq.h @@ -36,12 +36,33 @@ static inline void qemu_irq_pulse(qemu_irq irq) /* * Init a single IRQ. The irq is assigned with a handler, an opaque data - * and the interrupt number. + * and the interrupt number. The caller must free this with qemu_free_irq(). + * If you are using this inside a device's init or realize method, then + * qemu_init_irq_child() is probably a better choice to avoid the need + * to manually clean up the IRQ. */ void qemu_init_irq(IRQState *irq, qemu_irq_handler handler, void *opaque, int n); /** + * qemu_init_irq_child: Initialize IRQ and make it a QOM child + * @parent: QOM object which owns this IRQ + * @propname: child property name + * @irq: pointer to IRQState to initialize + * @handler: handler function for incoming interrupts + * @opaque: opaque data to pass to @handler + * @n: interrupt number to pass to @handler + * + * Init a single IRQ and make the IRQ object a child of @parent with + * the child-property name @propname. The IRQ object will thus be + * automatically freed when @parent is destroyed. + */ +void qemu_init_irq_child(Object *parent, const char *propname, + IRQState *irq, qemu_irq_handler handler, + void *opaque, int n); + + +/** * qemu_init_irqs: Initialize an array of IRQs. * * @irq: Array of IRQs to initialize diff --git a/include/hw/isa/vt82c686.h b/include/hw/isa/vt82c686.h index da1722d..ace9e66 100644 --- a/include/hw/isa/vt82c686.h +++ b/include/hw/isa/vt82c686.h @@ -2,7 +2,7 @@ #define HW_VT82C686_H #include "hw/pci/pci_device.h" -#include "audio/audio.h" +#include "qemu/audio.h" #define TYPE_VT82C686B_ISA "vt82c686b-isa" #define TYPE_VT82C686B_USB_UHCI "vt82c686b-usb-uhci" @@ -24,7 +24,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(ViaAC97State, VIA_AC97); struct ViaAC97State { PCIDevice dev; - QEMUSoundCard card; + AudioBackend *audio_be; MemoryRegion sgd; MemoryRegion fm; MemoryRegion midi; diff --git a/include/hw/loader.h b/include/hw/loader.h index d280dc3..d035e72 100644 --- a/include/hw/loader.h +++ b/include/hw/loader.h @@ -1,6 +1,7 @@ #ifndef LOADER_H #define LOADER_H #include "hw/nvram/fw_cfg.h" +#include "qemu/typedefs.h" /* loader.c */ /** @@ -10,7 +11,7 @@ * Returns the size of the image file on success, -1 otherwise. * On error, errno is also set as appropriate. */ -int64_t get_image_size(const char *filename); +int64_t get_image_size(const char *filename, Error **errp); /** * load_image_size: load an image file into specified buffer * @filename: Path to the image file @@ -41,7 +42,8 @@ ssize_t load_image_size(const char *filename, void *addr, size_t size); * Returns the size of the loaded image on success, -1 otherwise. */ ssize_t load_image_targphys_as(const char *filename, - hwaddr addr, uint64_t max_sz, AddressSpace *as); + hwaddr addr, uint64_t max_sz, AddressSpace *as, + Error **errp); /**load_targphys_hex_as: * @filename: Path to the .hex file @@ -61,7 +63,7 @@ ssize_t load_targphys_hex_as(const char *filename, hwaddr *entry, * an AddressSpace. */ ssize_t load_image_targphys(const char *filename, hwaddr, - uint64_t max_sz); + uint64_t max_sz, Error **errp); /** * load_image_mr: load an image into a memory region @@ -270,8 +272,6 @@ int rom_add_elf_program(const char *name, GMappedFile *mapped_file, void *data, AddressSpace *as); int rom_check_and_register_reset(void); void rom_set_fw(FWCfgState *f); -void rom_set_order_override(int order); -void rom_reset_order_override(void); /** * rom_transaction_begin: diff --git a/include/hw/loongarch/boot.h b/include/hw/loongarch/boot.h index b3b870d..9819f7f 100644 --- a/include/hw/loongarch/boot.h +++ b/include/hw/loongarch/boot.h @@ -102,11 +102,10 @@ struct loongarch_boot_info { const char *kernel_cmdline; const char *initrd_filename; uint64_t a0, a1, a2; + uint64_t initrd_addr; + uint64_t initrd_size; }; -extern struct memmap_entry *memmap_table; -extern unsigned memmap_entries; - struct memmap_entry { uint64_t address; uint64_t length; diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h index 2b7d199..27b1755 100644 --- a/include/hw/loongarch/virt.h +++ b/include/hw/loongarch/virt.h @@ -13,28 +13,84 @@ #include "hw/block/flash.h" #include "hw/loongarch/boot.h" +/* IOCSR region */ +#define VERSION_REG 0x0 +#define FEATURE_REG 0x8 +#define IOCSRF_TEMP 0 +#define IOCSRF_NODECNT 1 +#define IOCSRF_MSI 2 +#define IOCSRF_EXTIOI 3 +#define IOCSRF_CSRIPI 4 +#define IOCSRF_FREQCSR 5 +#define IOCSRF_FREQSCALE 6 +#define IOCSRF_DVFSV1 7 +#define IOCSRF_GMOD 9 +#define IOCSRF_VM 11 +#define IOCSRF_DMSI 15 +#define VENDOR_REG 0x10 +#define CPUNAME_REG 0x20 +#define MISC_FUNC_REG 0x420 +#define IOCSRM_EXTIOI_EN 48 +#define IOCSRM_EXTIOI_INT_ENCODE 49 +#define IOCSRM_DMSI_EN 51 + #define LOONGARCH_MAX_CPUS 256 -#define VIRT_FWCFG_BASE 0x1e020000UL +/* MMIO memory region */ +#define VIRT_PCH_REG_BASE 0x10000000UL +#define VIRT_PCH_REG_SIZE 0x400 +#define VIRT_RTC_REG_BASE 0x100d0100UL +#define VIRT_RTC_LEN 0x100 +#define VIRT_PLATFORM_BUS_BASEADDRESS 0x16000000UL +#define VIRT_PLATFORM_BUS_SIZE 0x02000000 +#define VIRT_PCI_IO_BASE 0x18004000UL +#define VIRT_PCI_IO_OFFSET 0x4000 +#define VIRT_PCI_IO_SIZE 0xC000 #define VIRT_BIOS_BASE 0x1c000000UL -#define VIRT_BIOS_SIZE (16 * MiB) +#define VIRT_BIOS_SIZE 0x01000000UL #define VIRT_FLASH_SECTOR_SIZE (256 * KiB) #define VIRT_FLASH0_BASE VIRT_BIOS_BASE #define VIRT_FLASH0_SIZE VIRT_BIOS_SIZE #define VIRT_FLASH1_BASE 0x1d000000UL -#define VIRT_FLASH1_SIZE (16 * MiB) +#define VIRT_FLASH1_SIZE 0x01000000UL +#define VIRT_FWCFG_BASE 0x1e020000UL +#define VIRT_UART_BASE 0x1fe001e0UL +#define VIRT_UART_SIZE 0x100 +#define VIRT_PCI_CFG_BASE 0x20000000UL +#define VIRT_PCI_CFG_SIZE 0x08000000UL +#define VIRT_DINTC_BASE 0x2FE00000UL +#define VIRT_DINTC_SIZE 0x00100000UL +#define VIRT_PCH_MSI_ADDR_LOW 0x2FF00000UL +#define VIRT_PCH_MSI_SIZE 0x8 +#define VIRT_PCI_MEM_BASE 0x40000000UL +#define VIRT_PCI_MEM_SIZE 0x40000000UL #define VIRT_LOWMEM_BASE 0 #define VIRT_LOWMEM_SIZE 0x10000000 +#define FDT_BASE 0x100000 #define VIRT_HIGHMEM_BASE 0x80000000 #define VIRT_GED_EVT_ADDR 0x100e0000 -#define VIRT_GED_MEM_ADDR (VIRT_GED_EVT_ADDR + ACPI_GED_EVT_SEL_LEN) -#define VIRT_GED_REG_ADDR (VIRT_GED_MEM_ADDR + MEMORY_HOTPLUG_IO_LEN) -#define VIRT_GED_CPUHP_ADDR (VIRT_GED_REG_ADDR + ACPI_GED_REG_COUNT) +#define VIRT_GED_MEM_ADDR QEMU_ALIGN_UP(VIRT_GED_EVT_ADDR + ACPI_GED_EVT_SEL_LEN, 4) +#define VIRT_GED_REG_ADDR QEMU_ALIGN_UP(VIRT_GED_MEM_ADDR + MEMORY_HOTPLUG_IO_LEN, 4) +#define VIRT_GED_CPUHP_ADDR QEMU_ALIGN_UP(VIRT_GED_REG_ADDR + ACPI_GED_REG_COUNT, 4) -#define COMMAND_LINE_SIZE 512 +/* + * GSI_BASE is hard-coded with 64 in linux kernel, else kernel fails to boot + * 0 - 15 GSI for ISA devices even if there is no ISA devices + * 16 - 63 GSI for CPU devices such as timers/perf monitor etc + * 64 - GSI for external devices + */ +#define VIRT_PCH_PIC_IRQ_NUM 32 +#define VIRT_GSI_BASE 64 +#define VIRT_DEVICE_IRQS 16 +#define VIRT_UART_IRQ (VIRT_GSI_BASE + 2) +#define VIRT_UART_COUNT 4 +#define VIRT_RTC_IRQ (VIRT_GSI_BASE + 6) +#define VIRT_SCI_IRQ (VIRT_GSI_BASE + 7) +#define VIRT_PLATFORM_BUS_IRQ (VIRT_GSI_BASE + 8) +#define VIRT_PLATFORM_BUS_NUM_IRQS 2 -#define FDT_BASE 0x100000 +#define COMMAND_LINE_SIZE 512 struct LoongArchVirtMachineState { /*< private >*/ @@ -50,6 +106,7 @@ struct LoongArchVirtMachineState { Notifier powerdown_notifier; OnOffAuto acpi; OnOffAuto veiointc; + OnOffAuto dmsi; char *oem_id; char *oem_table_id; DeviceState *acpi_ged; @@ -63,6 +120,11 @@ struct LoongArchVirtMachineState { struct loongarch_boot_info bootinfo; DeviceState *ipi; DeviceState *extioi; + struct memmap_entry *memmap_table; + unsigned int memmap_entries; + uint64_t misc_feature; + uint64_t misc_status; + DeviceState *dintc; }; #define TYPE_LOONGARCH_VIRT_MACHINE MACHINE_TYPE_NAME("virt") @@ -70,6 +132,15 @@ OBJECT_DECLARE_SIMPLE_TYPE(LoongArchVirtMachineState, LOONGARCH_VIRT_MACHINE) void virt_acpi_setup(LoongArchVirtMachineState *lvms); void virt_fdt_setup(LoongArchVirtMachineState *lvms); +static inline bool virt_has_dmsi(LoongArchVirtMachineState *lvms) +{ + if (!(lvms->misc_feature & BIT(IOCSRF_DMSI))) { + return false; + } + + return true; +} + static inline bool virt_is_veiointc_enabled(LoongArchVirtMachineState *lvms) { if (lvms->veiointc == ON_OFF_AUTO_OFF) { diff --git a/include/hw/misc/aspeed_hace.h b/include/hw/misc/aspeed_hace.h index 5d4aa19..d5d07c6 100644 --- a/include/hw/misc/aspeed_hace.h +++ b/include/hw/misc/aspeed_hace.h @@ -22,7 +22,6 @@ OBJECT_DECLARE_TYPE(AspeedHACEState, AspeedHACEClass, ASPEED_HACE) -#define ASPEED_HACE_NR_REGS (0x64 >> 2) #define ASPEED_HACE_MAX_SG 256 /* max number of entries */ struct AspeedHACEState { @@ -31,10 +30,8 @@ struct AspeedHACEState { MemoryRegion iomem; qemu_irq irq; - struct iovec iov_cache[ASPEED_HACE_MAX_SG]; - uint32_t regs[ASPEED_HACE_NR_REGS]; + uint32_t *regs; uint32_t total_req_len; - uint32_t iov_count; MemoryRegion *dram_mr; AddressSpace dram_as; @@ -46,11 +43,17 @@ struct AspeedHACEState { struct AspeedHACEClass { SysBusDeviceClass parent_class; + const MemoryRegionOps *reg_ops; uint32_t src_mask; uint32_t dest_mask; uint32_t key_mask; uint32_t hash_mask; + uint64_t nr_regs; bool raise_crypt_interrupt_workaround; + uint32_t src_hi_mask; + uint32_t dest_hi_mask; + uint32_t key_hi_mask; + bool has_dma64; }; #endif /* ASPEED_HACE_H */ diff --git a/include/hw/misc/aspeed_sbc.h b/include/hw/misc/aspeed_sbc.h index 405e678..7d640a0 100644 --- a/include/hw/misc/aspeed_sbc.h +++ b/include/hw/misc/aspeed_sbc.h @@ -10,9 +10,11 @@ #define ASPEED_SBC_H #include "hw/sysbus.h" +#include "hw/nvram/aspeed_otp.h" #define TYPE_ASPEED_SBC "aspeed.sbc" #define TYPE_ASPEED_AST2600_SBC TYPE_ASPEED_SBC "-ast2600" +#define TYPE_ASPEED_AST10X0_SBC TYPE_ASPEED_SBC "-ast10x0" OBJECT_DECLARE_TYPE(AspeedSBCState, AspeedSBCClass, ASPEED_SBC) #define ASPEED_SBC_NR_REGS (0x93c >> 2) @@ -36,10 +38,14 @@ struct AspeedSBCState { MemoryRegion iomem; uint32_t regs[ASPEED_SBC_NR_REGS]; + + AspeedOTPState otp; }; struct AspeedSBCClass { SysBusDeviceClass parent_class; + + bool has_otp; }; #endif /* ASPEED_SBC_H */ diff --git a/include/hw/misc/auxbus.h b/include/hw/misc/auxbus.h index ccd18ce..0051e03 100644 --- a/include/hw/misc/auxbus.h +++ b/include/hw/misc/auxbus.h @@ -29,13 +29,15 @@ #include "hw/qdev-core.h" #include "qom/object.h" -typedef struct AUXSlave AUXSlave; typedef enum AUXCommand AUXCommand; typedef enum AUXReply AUXReply; #define TYPE_AUXTOI2C "aux-to-i2c-bridge" OBJECT_DECLARE_SIMPLE_TYPE(AUXTOI2CState, AUXTOI2C) +#define TYPE_AUX_SLAVE "aux-slave" +OBJECT_DECLARE_SIMPLE_TYPE(AUXSlave, AUX_SLAVE) + enum AUXCommand { WRITE_I2C = 0, READ_I2C = 1, @@ -73,9 +75,6 @@ struct AUXBus { AddressSpace aux_addr_space; }; -#define TYPE_AUX_SLAVE "aux-slave" -OBJECT_DECLARE_SIMPLE_TYPE(AUXSlave, AUX_SLAVE) - struct AUXSlave { /* < private > */ DeviceState parent_obj; diff --git a/include/hw/misc/bcm2835_mphi.h b/include/hw/misc/bcm2835_mphi.h index 751363f..3f1997e 100644 --- a/include/hw/misc/bcm2835_mphi.h +++ b/include/hw/misc/bcm2835_mphi.h @@ -23,7 +23,8 @@ #define MPHI_MMIO_SIZE 0x1000 -typedef struct BCM2835MphiState BCM2835MphiState; +#define TYPE_BCM2835_MPHI "bcm2835-mphi" +OBJECT_DECLARE_SIMPLE_TYPE(BCM2835MphiState, BCM2835_MPHI) struct BCM2835MphiState { SysBusDevice parent_obj; @@ -37,8 +38,4 @@ struct BCM2835MphiState { uint32_t swirq; }; -#define TYPE_BCM2835_MPHI "bcm2835-mphi" - -OBJECT_DECLARE_SIMPLE_TYPE(BCM2835MphiState, BCM2835_MPHI) - #endif diff --git a/include/hw/misc/ivshmem-flat.h b/include/hw/misc/ivshmem-flat.h index 09bc3ab..d656e57 100644 --- a/include/hw/misc/ivshmem-flat.h +++ b/include/hw/misc/ivshmem-flat.h @@ -36,7 +36,7 @@ typedef struct IvshmemFTState IvshmemFTState; DECLARE_INSTANCE_CHECKER(IvshmemFTState, IVSHMEM_FLAT, TYPE_IVSHMEM_FLAT) -/* Ivshmem registers. See ./docs/specs/ivshmem-spec.txt for details. */ +/* Ivshmem registers. See docs/specs/ivshmem-spec.rst for details. */ enum ivshmem_registers { INTMASK = 0, INTSTATUS = 4, @@ -65,7 +65,7 @@ struct IvshmemFTState { QTAILQ_HEAD(, IvshmemPeer) peer; IvshmemPeer own; - CharBackend server_chr; + CharFrontend server_chr; /* IRQ */ qemu_irq irq; diff --git a/include/hw/misc/lasi.h b/include/hw/misc/lasi.h index 0bdfb11..0e95be1 100644 --- a/include/hw/misc/lasi.h +++ b/include/hw/misc/lasi.h @@ -13,8 +13,8 @@ #define LASI_H #include "system/address-spaces.h" -#include "hw/pci/pci_host.h" #include "hw/boards.h" +#include "hw/sysbus.h" #define TYPE_LASI_CHIP "lasi-chip" OBJECT_DECLARE_SIMPLE_TYPE(LasiState, LASI_CHIP) @@ -28,7 +28,9 @@ OBJECT_DECLARE_SIMPLE_TYPE(LasiState, LASI_CHIP) #define LASI_LPT 0x02000 #define LASI_AUDIO 0x04000 #define LASI_UART 0x05000 +#define LASI_SCSI 0x06000 #define LASI_LAN 0x07000 +#define LASI_PS2 0x08000 #define LASI_RTC 0x09000 #define LASI_FDC 0x0A000 @@ -61,7 +63,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(LasiState, LASI_CHIP) #define LASI_IRQ_PS2MOU_HPA 26 struct LasiState { - PCIHostState parent_obj; + SysBusDevice parent_obj; uint32_t irr; uint32_t imr; diff --git a/include/hw/misc/max78000_aes.h b/include/hw/misc/max78000_aes.h new file mode 100644 index 0000000..407c45e --- /dev/null +++ b/include/hw/misc/max78000_aes.h @@ -0,0 +1,68 @@ +/* + * MAX78000 AES + * + * Copyright (c) 2025 Jackson Donaldson <jcksn@duck.com> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef HW_MAX78000_AES_H +#define HW_MAX78000_AES_H + +#include "hw/sysbus.h" +#include "crypto/aes.h" +#include "qom/object.h" + +#define TYPE_MAX78000_AES "max78000-aes" +OBJECT_DECLARE_SIMPLE_TYPE(Max78000AesState, MAX78000_AES) + +#define CTRL 0 +#define STATUS 4 +#define INTFL 8 +#define INTEN 0xc +#define FIFO 0x10 + +#define KEY_BASE 0x400 +#define KEY_END 0x420 + +/* CTRL */ +#define TYPE (1 << 9 | 1 << 8) +#define KEY_SIZE (1 << 7 | 1 << 6) +#define OUTPUT_FLUSH (1 << 5) +#define INPUT_FLUSH (1 << 4) +#define START (1 << 3) + +#define AES_EN (1 << 0) + +/* STATUS */ +#define OUTPUT_FULL (1 << 4) +#define OUTPUT_EMPTY (1 << 3) +#define INPUT_FULL (1 << 2) +#define INPUT_EMPTY (1 << 1) +#define BUSY (1 << 0) + +/* INTFL*/ +#define DONE (1 << 0) + +struct Max78000AesState { + SysBusDevice parent_obj; + + MemoryRegion mmio; + + uint32_t ctrl; + uint32_t status; + uint32_t intfl; + uint32_t inten; + uint32_t data_index; + uint8_t data[16]; + + uint8_t key[32]; + AES_KEY internal_key; + + uint32_t result_index; + uint8_t result[16]; + + + qemu_irq irq; +}; + +#endif diff --git a/include/hw/misc/max78000_gcr.h b/include/hw/misc/max78000_gcr.h new file mode 100644 index 0000000..d5858a4 --- /dev/null +++ b/include/hw/misc/max78000_gcr.h @@ -0,0 +1,131 @@ +/* + * MAX78000 Global Control Register + * + * Copyright (c) 2025 Jackson Donaldson <jcksn@duck.com> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef HW_MAX78000_GCR_H +#define HW_MAX78000_GCR_H + +#include "hw/sysbus.h" +#include "qom/object.h" + +#define TYPE_MAX78000_GCR "max78000-gcr" +OBJECT_DECLARE_SIMPLE_TYPE(Max78000GcrState, MAX78000_GCR) + +#define SYSCTRL 0x0 +#define RST0 0x4 +#define CLKCTRL 0x8 +#define PM 0xc +#define PCLKDIV 0x18 +#define PCLKDIS0 0x24 +#define MEMCTRL 0x28 +#define MEMZ 0x2c +#define SYSST 0x40 +#define RST1 0x44 +#define PCKDIS1 0x48 +#define EVENTEN 0x4c +#define REVISION 0x50 +#define SYSIE 0x54 +#define ECCERR 0x64 +#define ECCED 0x68 +#define ECCIE 0x6c +#define ECCADDR 0x70 + +/* RST0 */ +#define SYSTEM_RESET (1 << 31) +#define PERIPHERAL_RESET (1 << 30) +#define SOFT_RESET (1 << 29) +#define UART2_RESET (1 << 28) + +#define ADC_RESET (1 << 26) +#define CNN_RESET (1 << 25) +#define TRNG_RESET (1 << 24) + +#define RTC_RESET (1 << 17) +#define I2C0_RESET (1 << 16) + +#define SPI1_RESET (1 << 13) +#define UART1_RESET (1 << 12) +#define UART0_RESET (1 << 11) + +#define TMR3_RESET (1 << 8) +#define TMR2_RESET (1 << 7) +#define TMR1_RESET (1 << 6) +#define TMR0_RESET (1 << 5) + +#define GPIO1_RESET (1 << 3) +#define GPIO0_RESET (1 << 2) +#define WDT0_RESET (1 << 1) +#define DMA_RESET (1 << 0) + +/* CLKCTRL */ +#define SYSCLK_RDY (1 << 13) + +/* MEMZ */ +#define ram0 (1 << 0) +#define ram1 (1 << 1) +#define ram2 (1 << 2) +#define ram3 (1 << 3) + +/* RST1 */ +#define CPU1_RESET (1 << 31) + +#define SIMO_RESET (1 << 25) +#define DVS_RESET (1 << 24) + +#define I2C2_RESET (1 << 20) +#define I2S_RESET (1 << 19) + +#define SMPHR_RESET (1 << 16) + +#define SPI0_RESET (1 << 11) +#define AES_RESET (1 << 10) +#define CRC_RESET (1 << 9) + +#define PT_RESET (1 << 1) +#define I2C1_RESET (1 << 0) + + +#define SYSRAM0_START 0x20000000 +#define SYSRAM1_START 0x20008000 +#define SYSRAM2_START 0x20010000 +#define SYSRAM3_START 0x2001C000 + +struct Max78000GcrState { + SysBusDevice parent_obj; + + MemoryRegion mmio; + + uint32_t sysctrl; + uint32_t rst0; + uint32_t clkctrl; + uint32_t pm; + uint32_t pclkdiv; + uint32_t pclkdis0; + uint32_t memctrl; + uint32_t memz; + uint32_t sysst; + uint32_t rst1; + uint32_t pckdis1; + uint32_t eventen; + uint32_t revision; + uint32_t sysie; + uint32_t eccerr; + uint32_t ecced; + uint32_t eccie; + uint32_t eccaddr; + + MemoryRegion *sram; + AddressSpace sram_as; + + DeviceState *uart0; + DeviceState *uart1; + DeviceState *uart2; + DeviceState *trng; + DeviceState *aes; + +}; + +#endif diff --git a/include/hw/misc/max78000_icc.h b/include/hw/misc/max78000_icc.h new file mode 100644 index 0000000..6fe2bb7 --- /dev/null +++ b/include/hw/misc/max78000_icc.h @@ -0,0 +1,33 @@ +/* + * MAX78000 Instruction Cache + * + * Copyright (c) 2025 Jackson Donaldson <jcksn@duck.com> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_MAX78000_ICC_H +#define HW_MAX78000_ICC_H + +#include "hw/sysbus.h" +#include "qom/object.h" + +#define TYPE_MAX78000_ICC "max78000-icc" +OBJECT_DECLARE_SIMPLE_TYPE(Max78000IccState, MAX78000_ICC) + +#define ICC_INFO 0x0 +#define ICC_SZ 0x4 +#define ICC_CTRL 0x100 +#define ICC_INVALIDATE 0x700 + +struct Max78000IccState { + SysBusDevice parent_obj; + + MemoryRegion mmio; + + uint32_t info; + uint32_t sz; + uint32_t ctrl; +}; + +#endif diff --git a/include/hw/misc/max78000_trng.h b/include/hw/misc/max78000_trng.h new file mode 100644 index 0000000..c5a8129 --- /dev/null +++ b/include/hw/misc/max78000_trng.h @@ -0,0 +1,35 @@ +/* + * MAX78000 True Random Number Generator + * + * Copyright (c) 2025 Jackson Donaldson <jcksn@duck.com> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef HW_MAX78000_TRNG_H +#define HW_MAX78000_TRNG_H + +#include "hw/sysbus.h" +#include "qom/object.h" + +#define TYPE_MAX78000_TRNG "max78000-trng" +OBJECT_DECLARE_SIMPLE_TYPE(Max78000TrngState, MAX78000_TRNG) + +#define CTRL 0 +#define STATUS 4 +#define DATA 8 + +#define RND_IE (1 << 1) + +struct Max78000TrngState { + SysBusDevice parent_obj; + + MemoryRegion mmio; + + uint32_t ctrl; + uint32_t status; + uint32_t data; + + qemu_irq irq; +}; + +#endif diff --git a/include/hw/misc/npcm7xx_pwm.h b/include/hw/misc/npcm7xx_pwm.h index bf95344..df92726 100644 --- a/include/hw/misc/npcm7xx_pwm.h +++ b/include/hw/misc/npcm7xx_pwm.h @@ -35,8 +35,8 @@ * value of 100,000 the duty cycle for that PWM is 10%. */ #define NPCM7XX_PWM_MAX_DUTY 1000000 - -typedef struct NPCM7xxPWMState NPCM7xxPWMState; +#define TYPE_NPCM7XX_PWM "npcm7xx-pwm" +OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxPWMState, NPCM7XX_PWM) /** * struct NPCM7xxPWM - The state of a single PWM channel. @@ -100,7 +100,4 @@ struct NPCM7xxPWMState { uint32_t piir; }; -#define TYPE_NPCM7XX_PWM "npcm7xx-pwm" -OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxPWMState, NPCM7XX_PWM) - #endif /* NPCM7XX_PWM_H */ diff --git a/include/hw/misc/xlnx-versal-crl.h b/include/hw/misc/xlnx-versal-crl.h index dba6d35..49ed500 100644 --- a/include/hw/misc/xlnx-versal-crl.h +++ b/include/hw/misc/xlnx-versal-crl.h @@ -2,6 +2,7 @@ * QEMU model of the Clock-Reset-LPD (CRL). * * Copyright (c) 2022 Xilinx Inc. + * Copyright (c) 2025 Advanced Micro Devices, Inc. * SPDX-License-Identifier: GPL-2.0-or-later * * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com> @@ -12,9 +13,16 @@ #include "hw/sysbus.h" #include "hw/register.h" #include "target/arm/cpu-qom.h" +#include "hw/arm/xlnx-versal-version.h" +#define TYPE_XLNX_VERSAL_CRL_BASE "xlnx-versal-crl-base" #define TYPE_XLNX_VERSAL_CRL "xlnx-versal-crl" +#define TYPE_XLNX_VERSAL2_CRL "xlnx-versal2-crl" + +OBJECT_DECLARE_TYPE(XlnxVersalCRLBase, XlnxVersalCRLBaseClass, + XLNX_VERSAL_CRL_BASE) OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCRL, XLNX_VERSAL_CRL) +OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersal2CRL, XLNX_VERSAL2_CRL) REG32(ERR_CTRL, 0x0) FIELD(ERR_CTRL, SLVERR_ENABLE, 0, 1) @@ -214,22 +222,369 @@ REG32(PSM_RST_MODE, 0x370) #define CRL_R_MAX (R_PSM_RST_MODE + 1) -#define RPU_MAX_CPU 2 +REG32(VERSAL2_ERR_CTRL, 0x0) +REG32(VERSAL2_WPROT, 0x1c) + FIELD(VERSAL2_WPROT, ACTIVE, 0, 1) +REG32(VERSAL2_RPLL_CTRL, 0x40) + FIELD(VERSAL2_RPLL_CTRL, POST_SRC, 24, 3) + FIELD(VERSAL2_RPLL_CTRL, PRE_SRC, 20, 3) + FIELD(VERSAL2_RPLL_CTRL, CLKOUTDIV, 16, 2) + FIELD(VERSAL2_RPLL_CTRL, FBDIV, 8, 8) + FIELD(VERSAL2_RPLL_CTRL, BYPASS, 3, 1) + FIELD(VERSAL2_RPLL_CTRL, RESET, 0, 1) +REG32(VERSAL2_RPLL_CFG, 0x44) + FIELD(VERSAL2_RPLL_CFG, LOCK_DLY, 25, 7) + FIELD(VERSAL2_RPLL_CFG, LOCK_CNT, 13, 10) + FIELD(VERSAL2_RPLL_CFG, LFHF, 10, 2) + FIELD(VERSAL2_RPLL_CFG, CP, 5, 4) + FIELD(VERSAL2_RPLL_CFG, RES, 0, 4) +REG32(VERSAL2_FLXPLL_CTRL, 0x50) + FIELD(VERSAL2_FLXPLL_CTRL, POST_SRC, 24, 3) + FIELD(VERSAL2_FLXPLL_CTRL, PRE_SRC, 20, 3) + FIELD(VERSAL2_FLXPLL_CTRL, CLKOUTDIV, 16, 2) + FIELD(VERSAL2_FLXPLL_CTRL, FBDIV, 8, 8) + FIELD(VERSAL2_FLXPLL_CTRL, BYPASS, 3, 1) + FIELD(VERSAL2_FLXPLL_CTRL, RESET, 0, 1) +REG32(VERSAL2_FLXPLL_CFG, 0x54) + FIELD(VERSAL2_FLXPLL_CFG, LOCK_DLY, 25, 7) + FIELD(VERSAL2_FLXPLL_CFG, LOCK_CNT, 13, 10) + FIELD(VERSAL2_FLXPLL_CFG, LFHF, 10, 2) + FIELD(VERSAL2_FLXPLL_CFG, CP, 5, 4) + FIELD(VERSAL2_FLXPLL_CFG, RES, 0, 4) +REG32(VERSAL2_PLL_STATUS, 0x60) + FIELD(VERSAL2_PLL_STATUS, FLXPLL_STABLE, 3, 1) + FIELD(VERSAL2_PLL_STATUS, RPLL_STABLE, 2, 1) + FIELD(VERSAL2_PLL_STATUS, FLXPLL_LOCK, 1, 1) + FIELD(VERSAL2_PLL_STATUS, RPLL_LOCK, 0, 1) +REG32(VERSAL2_RPLL_TO_XPD_CTRL, 0x100) + FIELD(VERSAL2_RPLL_TO_XPD_CTRL, DIVISOR0, 8, 10) +REG32(VERSAL2_LPX_TOP_SWITCH_CTRL, 0x104) + FIELD(VERSAL2_LPX_TOP_SWITCH_CTRL, CLKACT_ADMA, 26, 1) + FIELD(VERSAL2_LPX_TOP_SWITCH_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_LPX_TOP_SWITCH_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_LPX_TOP_SWITCH_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_LPX_LSBUS_CLK_CTRL, 0x108) + FIELD(VERSAL2_LPX_LSBUS_CLK_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_LPX_LSBUS_CLK_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_LPX_LSBUS_CLK_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_RPU_CLK_CTRL, 0x10c) + FIELD(VERSAL2_RPU_CLK_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_RPU_CLK_CTRL, CLKACT_CLUSTERE, 24, 1) + FIELD(VERSAL2_RPU_CLK_CTRL, CLKACT_CLUSTERD, 23, 1) + FIELD(VERSAL2_RPU_CLK_CTRL, CLKACT_CLUSTERC, 22, 1) + FIELD(VERSAL2_RPU_CLK_CTRL, CLKACT_CLUSTERB, 21, 1) + FIELD(VERSAL2_RPU_CLK_CTRL, CLKACT_CLUSTERA, 20, 1) + FIELD(VERSAL2_RPU_CLK_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_RPU_CLK_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_OCM_CLK_CTRL, 0x120) + FIELD(VERSAL2_OCM_CLK_CTRL, CLKACT_OCM3, 24, 1) + FIELD(VERSAL2_OCM_CLK_CTRL, CLKACT_OCM2, 23, 1) + FIELD(VERSAL2_OCM_CLK_CTRL, CLKACT_OCM1, 22, 1) + FIELD(VERSAL2_OCM_CLK_CTRL, CLKACT_OCM0, 21, 1) +REG32(VERSAL2_IOU_SWITCH_CLK_CTRL, 0x124) + FIELD(VERSAL2_IOU_SWITCH_CLK_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_IOU_SWITCH_CLK_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_IOU_SWITCH_CLK_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_GEM0_REF_CTRL, 0x128) + FIELD(VERSAL2_GEM0_REF_CTRL, CLKACT_RX, 27, 1) + FIELD(VERSAL2_GEM0_REF_CTRL, CLKACT_TX, 26, 1) + FIELD(VERSAL2_GEM0_REF_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_GEM0_REF_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_GEM0_REF_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_GEM1_REF_CTRL, 0x12c) + FIELD(VERSAL2_GEM1_REF_CTRL, CLKACT_RX, 27, 1) + FIELD(VERSAL2_GEM1_REF_CTRL, CLKACT_TX, 26, 1) + FIELD(VERSAL2_GEM1_REF_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_GEM1_REF_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_GEM1_REF_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_GEM_TSU_REF_CLK_CTRL, 0x130) + FIELD(VERSAL2_GEM_TSU_REF_CLK_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_GEM_TSU_REF_CLK_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_GEM_TSU_REF_CLK_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_USB0_BUS_REF_CLK_CTRL, 0x134) + FIELD(VERSAL2_USB0_BUS_REF_CLK_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_USB0_BUS_REF_CLK_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_USB0_BUS_REF_CLK_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_USB1_BUS_REF_CLK_CTRL, 0x138) + FIELD(VERSAL2_USB1_BUS_REF_CLK_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_USB1_BUS_REF_CLK_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_USB1_BUS_REF_CLK_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_UART0_REF_CLK_CTRL, 0x13c) + FIELD(VERSAL2_UART0_REF_CLK_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_UART0_REF_CLK_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_UART0_REF_CLK_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_UART1_REF_CLK_CTRL, 0x140) + FIELD(VERSAL2_UART1_REF_CLK_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_UART1_REF_CLK_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_UART1_REF_CLK_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_SPI0_REF_CLK_CTRL, 0x144) + FIELD(VERSAL2_SPI0_REF_CLK_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_SPI0_REF_CLK_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_SPI0_REF_CLK_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_SPI1_REF_CLK_CTRL, 0x148) + FIELD(VERSAL2_SPI1_REF_CLK_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_SPI1_REF_CLK_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_SPI1_REF_CLK_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_CAN0_REF_2X_CTRL, 0x14c) + FIELD(VERSAL2_CAN0_REF_2X_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_CAN0_REF_2X_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_CAN0_REF_2X_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_CAN1_REF_2X_CTRL, 0x150) + FIELD(VERSAL2_CAN1_REF_2X_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_CAN1_REF_2X_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_CAN1_REF_2X_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_CAN2_REF_2X_CTRL, 0x154) + FIELD(VERSAL2_CAN2_REF_2X_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_CAN2_REF_2X_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_CAN2_REF_2X_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_CAN3_REF_2X_CTRL, 0x158) + FIELD(VERSAL2_CAN3_REF_2X_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_CAN3_REF_2X_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_CAN3_REF_2X_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_I3C0_REF_CTRL, 0x15c) + FIELD(VERSAL2_I3C0_REF_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_I3C0_REF_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_I3C0_REF_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_I3C1_REF_CTRL, 0x160) + FIELD(VERSAL2_I3C1_REF_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_I3C1_REF_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_I3C1_REF_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_I3C2_REF_CTRL, 0x164) + FIELD(VERSAL2_I3C2_REF_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_I3C2_REF_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_I3C2_REF_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_I3C3_REF_CTRL, 0x168) + FIELD(VERSAL2_I3C3_REF_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_I3C3_REF_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_I3C3_REF_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_I3C4_REF_CTRL, 0x16c) + FIELD(VERSAL2_I3C4_REF_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_I3C4_REF_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_I3C4_REF_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_I3C5_REF_CTRL, 0x170) + FIELD(VERSAL2_I3C5_REF_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_I3C5_REF_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_I3C5_REF_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_I3C6_REF_CTRL, 0x174) + FIELD(VERSAL2_I3C6_REF_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_I3C6_REF_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_I3C6_REF_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_I3C7_REF_CTRL, 0x178) + FIELD(VERSAL2_I3C7_REF_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_I3C7_REF_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_I3C7_REF_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_DBG_LPX_CTRL, 0x17c) + FIELD(VERSAL2_DBG_LPX_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_DBG_LPX_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_DBG_LPX_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_TIMESTAMP_REF_CTRL, 0x180) + FIELD(VERSAL2_TIMESTAMP_REF_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_TIMESTAMP_REF_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_TIMESTAMP_REF_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_SAFETY_CHK, 0x184) +REG32(VERSAL2_ASU_CLK_CTRL, 0x188) + FIELD(VERSAL2_ASU_CLK_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_ASU_CLK_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_DBG_TSTMP_CLK_CTRL, 0x18c) + FIELD(VERSAL2_DBG_TSTMP_CLK_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_DBG_TSTMP_CLK_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_DBG_TSTMP_CLK_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_MMI_TOPSW_CLK_CTRL, 0x190) + FIELD(VERSAL2_MMI_TOPSW_CLK_CTRL, CLKACT, 25, 1) + FIELD(VERSAL2_MMI_TOPSW_CLK_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_MMI_TOPSW_CLK_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_WWDT_PLL_CLK_CTRL, 0x194) + FIELD(VERSAL2_WWDT_PLL_CLK_CTRL, DIVISOR0, 8, 10) + FIELD(VERSAL2_WWDT_PLL_CLK_CTRL, SRCSEL, 0, 3) +REG32(VERSAL2_RCLK_CTRL, 0x1a0) + FIELD(VERSAL2_RCLK_CTRL, CLKACT, 8, 6) + FIELD(VERSAL2_RCLK_CTRL, SELECT, 0, 6) +REG32(VERSAL2_RST_RPU_A, 0x310) + FIELD(VERSAL2_RST_RPU_A, TOPRESET, 16, 1) + FIELD(VERSAL2_RST_RPU_A, CORE1_POR, 9, 1) + FIELD(VERSAL2_RST_RPU_A, CORE0_POR, 8, 1) + FIELD(VERSAL2_RST_RPU_A, CORE1_RESET, 1, 1) + FIELD(VERSAL2_RST_RPU_A, CORE0_RESET, 0, 1) +REG32(VERSAL2_RST_RPU_B, 0x314) + FIELD(VERSAL2_RST_RPU_B, TOPRESET, 16, 1) + FIELD(VERSAL2_RST_RPU_B, CORE1_POR, 9, 1) + FIELD(VERSAL2_RST_RPU_B, CORE0_POR, 8, 1) + FIELD(VERSAL2_RST_RPU_B, CORE1_RESET, 1, 1) + FIELD(VERSAL2_RST_RPU_B, CORE0_RESET, 0, 1) +REG32(VERSAL2_RST_RPU_C, 0x318) + FIELD(VERSAL2_RST_RPU_C, TOPRESET, 16, 1) + FIELD(VERSAL2_RST_RPU_C, CORE1_POR, 9, 1) + FIELD(VERSAL2_RST_RPU_C, CORE0_POR, 8, 1) + FIELD(VERSAL2_RST_RPU_C, CORE1_RESET, 1, 1) + FIELD(VERSAL2_RST_RPU_C, CORE0_RESET, 0, 1) +REG32(VERSAL2_RST_RPU_D, 0x31c) + FIELD(VERSAL2_RST_RPU_D, TOPRESET, 16, 1) + FIELD(VERSAL2_RST_RPU_D, CORE1_POR, 9, 1) + FIELD(VERSAL2_RST_RPU_D, CORE0_POR, 8, 1) + FIELD(VERSAL2_RST_RPU_D, CORE1_RESET, 1, 1) + FIELD(VERSAL2_RST_RPU_D, CORE0_RESET, 0, 1) +REG32(VERSAL2_RST_RPU_E, 0x320) + FIELD(VERSAL2_RST_RPU_E, TOPRESET, 16, 1) + FIELD(VERSAL2_RST_RPU_E, CORE1_POR, 9, 1) + FIELD(VERSAL2_RST_RPU_E, CORE0_POR, 8, 1) + FIELD(VERSAL2_RST_RPU_E, CORE1_RESET, 1, 1) + FIELD(VERSAL2_RST_RPU_E, CORE0_RESET, 0, 1) +REG32(VERSAL2_RST_RPU_GD_0, 0x324) + FIELD(VERSAL2_RST_RPU_GD_0, RESET, 1, 1) + FIELD(VERSAL2_RST_RPU_GD_0, TOP_RESET, 0, 1) +REG32(VERSAL2_RST_RPU_GD_1, 0x328) + FIELD(VERSAL2_RST_RPU_GD_1, RESET, 1, 1) + FIELD(VERSAL2_RST_RPU_GD_1, TOP_RESET, 0, 1) +REG32(VERSAL2_RST_ASU_GD, 0x32c) + FIELD(VERSAL2_RST_ASU_GD, RESET, 1, 1) + FIELD(VERSAL2_RST_ASU_GD, TOP_RESET, 0, 1) +REG32(VERSAL2_RST_ADMA, 0x334) + FIELD(VERSAL2_RST_ADMA, RESET, 0, 1) +REG32(VERSAL2_RST_SDMA, 0x338) + FIELD(VERSAL2_RST_SDMA, RESET, 0, 1) +REG32(VERSAL2_RST_GEM0, 0x33c) + FIELD(VERSAL2_RST_GEM0, RESET, 0, 1) +REG32(VERSAL2_RST_GEM1, 0x340) + FIELD(VERSAL2_RST_GEM1, RESET, 0, 1) +REG32(VERSAL2_RST_USB0, 0x348) + FIELD(VERSAL2_RST_USB0, RESET, 0, 1) +REG32(VERSAL2_RST_USB1, 0x34c) + FIELD(VERSAL2_RST_USB1, RESET, 0, 1) +REG32(VERSAL2_RST_UART0, 0x350) + FIELD(VERSAL2_RST_UART0, RESET, 0, 1) +REG32(VERSAL2_RST_UART1, 0x354) + FIELD(VERSAL2_RST_UART1, RESET, 0, 1) +REG32(VERSAL2_RST_SPI0, 0x358) + FIELD(VERSAL2_RST_SPI0, RESET, 0, 1) +REG32(VERSAL2_RST_SPI1, 0x35c) + FIELD(VERSAL2_RST_SPI1, RESET, 0, 1) +REG32(VERSAL2_RST_CAN0, 0x360) + FIELD(VERSAL2_RST_CAN0, RESET, 0, 1) +REG32(VERSAL2_RST_CAN1, 0x364) + FIELD(VERSAL2_RST_CAN1, RESET, 0, 1) +REG32(VERSAL2_RST_CAN2, 0x368) + FIELD(VERSAL2_RST_CAN2, RESET, 0, 1) +REG32(VERSAL2_RST_CAN3, 0x36c) + FIELD(VERSAL2_RST_CAN3, RESET, 0, 1) +REG32(VERSAL2_RST_I3C0, 0x374) + FIELD(VERSAL2_RST_I3C0, RESET, 0, 1) +REG32(VERSAL2_RST_I3C1, 0x378) + FIELD(VERSAL2_RST_I3C1, RESET, 0, 1) +REG32(VERSAL2_RST_I3C2, 0x37c) + FIELD(VERSAL2_RST_I3C2, RESET, 0, 1) +REG32(VERSAL2_RST_I3C3, 0x380) + FIELD(VERSAL2_RST_I3C3, RESET, 0, 1) +REG32(VERSAL2_RST_I3C4, 0x384) + FIELD(VERSAL2_RST_I3C4, RESET, 0, 1) +REG32(VERSAL2_RST_I3C5, 0x388) + FIELD(VERSAL2_RST_I3C5, RESET, 0, 1) +REG32(VERSAL2_RST_I3C6, 0x38c) + FIELD(VERSAL2_RST_I3C6, RESET, 0, 1) +REG32(VERSAL2_RST_I3C7, 0x390) + FIELD(VERSAL2_RST_I3C7, RESET, 0, 1) +REG32(VERSAL2_RST_DBG_LPX, 0x398) + FIELD(VERSAL2_RST_DBG_LPX, RESET_HSDP, 1, 1) + FIELD(VERSAL2_RST_DBG_LPX, RESET, 0, 1) +REG32(VERSAL2_RST_GPIO, 0x39c) + FIELD(VERSAL2_RST_GPIO, RESET, 0, 1) +REG32(VERSAL2_RST_TTC, 0x3a0) + FIELD(VERSAL2_RST_TTC, TTC7_RESET, 7, 1) + FIELD(VERSAL2_RST_TTC, TTC6_RESET, 6, 1) + FIELD(VERSAL2_RST_TTC, TTC5_RESET, 5, 1) + FIELD(VERSAL2_RST_TTC, TTC4_RESET, 4, 1) + FIELD(VERSAL2_RST_TTC, TTC3_RESET, 3, 1) + FIELD(VERSAL2_RST_TTC, TTC2_RESET, 2, 1) + FIELD(VERSAL2_RST_TTC, TTC1_RESET, 1, 1) + FIELD(VERSAL2_RST_TTC, TTC0_RESET, 0, 1) +REG32(VERSAL2_RST_TIMESTAMP, 0x3a4) + FIELD(VERSAL2_RST_TIMESTAMP, RESET, 0, 1) +REG32(VERSAL2_RST_SWDT0, 0x3a8) + FIELD(VERSAL2_RST_SWDT0, RESET, 0, 1) +REG32(VERSAL2_RST_SWDT1, 0x3ac) + FIELD(VERSAL2_RST_SWDT1, RESET, 0, 1) +REG32(VERSAL2_RST_SWDT2, 0x3b0) + FIELD(VERSAL2_RST_SWDT2, RESET, 0, 1) +REG32(VERSAL2_RST_SWDT3, 0x3b4) + FIELD(VERSAL2_RST_SWDT3, RESET, 0, 1) +REG32(VERSAL2_RST_SWDT4, 0x3b8) + FIELD(VERSAL2_RST_SWDT4, RESET, 0, 1) +REG32(VERSAL2_RST_IPI, 0x3bc) + FIELD(VERSAL2_RST_IPI, RESET, 0, 1) +REG32(VERSAL2_RST_SYSMON, 0x3c0) + FIELD(VERSAL2_RST_SYSMON, CFG_RST, 0, 1) +REG32(VERSAL2_ASU_MB_RST_MODE, 0x3c4) + FIELD(VERSAL2_ASU_MB_RST_MODE, WAKEUP, 2, 1) + FIELD(VERSAL2_ASU_MB_RST_MODE, RST_MODE, 0, 2) +REG32(VERSAL2_FPX_TOPSW_MUX_CTRL, 0x3c8) + FIELD(VERSAL2_FPX_TOPSW_MUX_CTRL, SELECT, 0, 1) +REG32(VERSAL2_RST_FPX, 0x3d0) + FIELD(VERSAL2_RST_FPX, SRST, 1, 1) + FIELD(VERSAL2_RST_FPX, POR, 0, 1) +REG32(VERSAL2_RST_MMI, 0x3d4) + FIELD(VERSAL2_RST_MMI, POR, 0, 1) +REG32(VERSAL2_RST_OCM, 0x3d8) + FIELD(VERSAL2_RST_OCM, RESET_OCM3, 3, 1) + FIELD(VERSAL2_RST_OCM, RESET_OCM2, 2, 1) + FIELD(VERSAL2_RST_OCM, RESET_OCM1, 1, 1) + FIELD(VERSAL2_RST_OCM, RESET_OCM0, 0, 1) -struct XlnxVersalCRL { +#define VERSAL2_CRL_R_MAX (R_VERSAL2_RST_OCM + 1) + +struct XlnxVersalCRLBase { SysBusDevice parent_obj; + + uint32_t *regs; +}; + +struct XlnxVersalCRLBaseClass { + SysBusDeviceClass parent_class; + + DeviceState ** (*decode_periph_rst)(XlnxVersalCRLBase *s, hwaddr, size_t *); +}; + +struct XlnxVersalCRL { + XlnxVersalCRLBase parent_obj; qemu_irq irq; struct { - ARMCPU *cpu_r5[RPU_MAX_CPU]; + DeviceState *rpu[2]; DeviceState *adma[8]; DeviceState *uart[2]; DeviceState *gem[2]; - DeviceState *usb; + DeviceState *usb[1]; } cfg; - RegisterInfoArray *reg_array; uint32_t regs[CRL_R_MAX]; RegisterInfo regs_info[CRL_R_MAX]; }; + +struct XlnxVersal2CRL { + XlnxVersalCRLBase parent_obj; + + struct { + DeviceState *rpu[10]; + DeviceState *adma[8]; + DeviceState *sdma[8]; + DeviceState *uart[2]; + DeviceState *gem[2]; + DeviceState *usb[2]; + DeviceState *can[4]; + } cfg; + + RegisterInfo regs_info[VERSAL2_CRL_R_MAX]; + uint32_t regs[VERSAL2_CRL_R_MAX]; +}; + +static inline const char *xlnx_versal_crl_class_name(VersalVersion ver) +{ + switch (ver) { + case VERSAL_VER_VERSAL: + return TYPE_XLNX_VERSAL_CRL; + case VERSAL_VER_VERSAL2: + return TYPE_XLNX_VERSAL2_CRL; + default: + g_assert_not_reached(); + } +} + #endif diff --git a/include/hw/misc/xlnx-versal-xramc.h b/include/hw/misc/xlnx-versal-xramc.h index d3d1862..35e4e8b 100644 --- a/include/hw/misc/xlnx-versal-xramc.h +++ b/include/hw/misc/xlnx-versal-xramc.h @@ -90,7 +90,6 @@ typedef struct XlnxXramCtrl { unsigned int encoded_size; } cfg; - RegisterInfoArray *reg_array; uint32_t regs[XRAM_CTRL_R_MAX]; RegisterInfo regs_info[XRAM_CTRL_R_MAX]; } XlnxXramCtrl; diff --git a/include/hw/misc/xlnx-zynqmp-apu-ctrl.h b/include/hw/misc/xlnx-zynqmp-apu-ctrl.h index c3bf3c1..fbfe34a 100644 --- a/include/hw/misc/xlnx-zynqmp-apu-ctrl.h +++ b/include/hw/misc/xlnx-zynqmp-apu-ctrl.h @@ -85,7 +85,6 @@ struct XlnxZynqMPAPUCtrl { uint8_t cpu_pwrdwn_req; uint8_t cpu_in_wfi; - RegisterInfoArray *reg_array; uint32_t regs[APU_R_MAX]; RegisterInfo regs_info[APU_R_MAX]; }; diff --git a/include/hw/misc/xlnx-zynqmp-crf.h b/include/hw/misc/xlnx-zynqmp-crf.h index 02ef0bd..c746ae1 100644 --- a/include/hw/misc/xlnx-zynqmp-crf.h +++ b/include/hw/misc/xlnx-zynqmp-crf.h @@ -203,7 +203,6 @@ struct XlnxZynqMPCRF { MemoryRegion iomem; qemu_irq irq_ir; - RegisterInfoArray *reg_array; uint32_t regs[CRF_R_MAX]; RegisterInfo regs_info[CRF_R_MAX]; }; diff --git a/include/hw/net/cadence_gem.h b/include/hw/net/cadence_gem.h index 91ebb5c..e63941f 100644 --- a/include/hw/net/cadence_gem.h +++ b/include/hw/net/cadence_gem.h @@ -62,6 +62,7 @@ struct CadenceGEMState { uint8_t num_type2_screeners; uint32_t revision; uint16_t jumbo_max_len; + bool pcs_enabled; /* GEM registers backing store */ uint32_t regs[CADENCE_GEM_MAXREG]; @@ -81,6 +82,9 @@ struct CadenceGEMState { uint8_t phy_loop; /* Are we in phy loopback? */ + bool phy_connected; /* true if connected */ + struct CadenceGEMState *phy_consumer; + /* The current DMA descriptor pointers */ uint32_t rx_desc_addr[MAX_PRIORITY_QUEUES]; uint32_t tx_desc_addr[MAX_PRIORITY_QUEUES]; diff --git a/include/hw/net/lasi_82596.h b/include/hw/net/lasi_82596.h index 439356e..c46a4a1 100644 --- a/include/hw/net/lasi_82596.h +++ b/include/hw/net/lasi_82596.h @@ -25,7 +25,4 @@ struct SysBusI82596State { int val_index:1; }; -SysBusI82596State *lasi_82596_init(MemoryRegion *addr_space, hwaddr hpa, - qemu_irq irq, gboolean match_default); - #endif diff --git a/include/hw/net/xlnx-versal-canfd.h b/include/hw/net/xlnx-versal-canfd.h index ad3104d..396f90d 100644 --- a/include/hw/net/xlnx-versal-canfd.h +++ b/include/hw/net/xlnx-versal-canfd.h @@ -54,14 +54,6 @@ typedef struct XlnxVersalCANFDState { qemu_irq irq_addr_err; RegisterInfo reg_info[XLNX_VERSAL_CANFD_R_MAX]; - RegisterAccessInfo *tx_regs; - RegisterAccessInfo *rx0_regs; - RegisterAccessInfo *rx1_regs; - RegisterAccessInfo *af_regs; - RegisterAccessInfo *txe_regs; - RegisterAccessInfo *rx_mailbox_regs; - RegisterAccessInfo *af_mask_regs_mailbox; - uint32_t regs[XLNX_VERSAL_CANFD_R_MAX]; ptimer_state *canfd_timer; diff --git a/include/hw/nvram/aspeed_otp.h b/include/hw/nvram/aspeed_otp.h new file mode 100644 index 0000000..3752353 --- /dev/null +++ b/include/hw/nvram/aspeed_otp.h @@ -0,0 +1,33 @@ +/* + * ASPEED OTP (One-Time Programmable) memory + * + * Copyright (C) 2025 Aspeed + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef ASPEED_OTP_H +#define ASPEED_OTP_H + +#include "system/memory.h" +#include "hw/block/block.h" +#include "system/address-spaces.h" + +#define TYPE_ASPEED_OTP "aspeed-otp" +OBJECT_DECLARE_SIMPLE_TYPE(AspeedOTPState, ASPEED_OTP) + +typedef struct AspeedOTPState { + DeviceState parent_obj; + + BlockBackend *blk; + + uint64_t size; + + AddressSpace as; + + MemoryRegion mmio; + + uint8_t *storage; +} AspeedOTPState; + +#endif /* ASPEED_OTP_H */ diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h index 47578cc..d41b932 100644 --- a/include/hw/nvram/fw_cfg.h +++ b/include/hw/nvram/fw_cfg.h @@ -42,14 +42,6 @@ struct FWCfgDataGeneratorClass { typedef struct fw_cfg_file FWCfgFile; -#define FW_CFG_ORDER_OVERRIDE_VGA 70 -#define FW_CFG_ORDER_OVERRIDE_NIC 80 -#define FW_CFG_ORDER_OVERRIDE_USER 100 -#define FW_CFG_ORDER_OVERRIDE_DEVICE 110 - -void fw_cfg_set_order_override(FWCfgState *fw_cfg, int order); -void fw_cfg_reset_order_override(FWCfgState *fw_cfg); - typedef struct FWCfgFiles { uint32_t count; FWCfgFile f[]; @@ -75,8 +67,6 @@ struct FWCfgState { uint32_t cur_offset; Notifier machine_ready; - int fw_cfg_order_override; - bool dma_enabled; dma_addr_t dma_addr; AddressSpace *dma_as; diff --git a/include/hw/nvram/xlnx-bbram.h b/include/hw/nvram/xlnx-bbram.h index 58acbe9..af90900 100644 --- a/include/hw/nvram/xlnx-bbram.h +++ b/include/hw/nvram/xlnx-bbram.h @@ -47,7 +47,6 @@ struct XlnxBBRam { bool bbram8_wo; bool blk_ro; - RegisterInfoArray *reg_array; uint32_t regs[RMAX_XLNX_BBRAM]; RegisterInfo regs_info[RMAX_XLNX_BBRAM]; }; diff --git a/include/hw/pci-host/aspeed_pcie.h b/include/hw/pci-host/aspeed_pcie.h new file mode 100644 index 0000000..be53ea96 --- /dev/null +++ b/include/hw/pci-host/aspeed_pcie.h @@ -0,0 +1,137 @@ +/* + * ASPEED PCIe Host Controller + * + * Copyright (C) 2025 ASPEED Technology Inc. + * Copyright (c) 2022 Cédric Le Goater <clg@kaod.org> + * + * Authors: + * Cédric Le Goater <clg@kaod.org> + * Jamin Lin <jamin_lin@aspeedtech.com> + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Based on previous work from Cédric Le Goater. + * Modifications extend support for the ASPEED AST2600 and AST2700 platforms. + */ + +#ifndef ASPEED_PCIE_H +#define ASPEED_PCIE_H + +#include "hw/sysbus.h" +#include "hw/pci/pci_bridge.h" +#include "hw/pci/pcie_host.h" +#include "hw/pci/pcie_port.h" +#include "qom/object.h" + +typedef struct AspeedPCIECfgTxDesc { + uint32_t desc0; + uint32_t desc1; + uint32_t desc2; + uint32_t desc3; + uint32_t wdata; + uint32_t rdata_reg; +} AspeedPCIECfgTxDesc; + +typedef struct AspeedPCIERcRegs { + uint32_t int_en_reg; + uint32_t int_sts_reg; + uint32_t msi_sts0_reg; + uint32_t msi_sts1_reg; +} AspeedPCIERcRegs; + +typedef struct AspeedPCIERegMap { + AspeedPCIERcRegs rc; +} AspeedPCIERegMap; + +#define TYPE_ASPEED_PCIE_ROOT_PORT "aspeed.pcie-root-port" +OBJECT_DECLARE_SIMPLE_TYPE(AspeedPCIERootPortState, ASPEED_PCIE_ROOT_PORT) + +typedef struct AspeedPCIERootPortState { + PCIESlot parent_obj; +} AspeedPCIERootPortState; + +#define TYPE_ASPEED_PCIE_ROOT_DEVICE "aspeed.pcie-root-device" +OBJECT_DECLARE_SIMPLE_TYPE(AspeedPCIERootDeviceState, ASPEED_PCIE_ROOT_DEVICE); + +struct AspeedPCIERootDeviceState { + PCIBridge parent_obj; +}; + +#define TYPE_ASPEED_PCIE_RC "aspeed.pcie-rc" +OBJECT_DECLARE_SIMPLE_TYPE(AspeedPCIERcState, ASPEED_PCIE_RC); + +struct AspeedPCIERcState { + PCIExpressHost parent_obj; + + MemoryRegion iommu_root; + AddressSpace iommu_as; + MemoryRegion dram_alias; + MemoryRegion *dram_mr; + MemoryRegion mmio_window; + MemoryRegion msi_window; + MemoryRegion io_window; + MemoryRegion mmio; + MemoryRegion io; + + uint64_t dram_base; + uint32_t msi_addr; + uint32_t rp_addr; + uint32_t bus_nr; + char name[16]; + bool has_rd; + qemu_irq irq; + + AspeedPCIERootDeviceState root_device; + AspeedPCIERootPortState root_port; +}; + +/* Bridge between AHB bus and PCIe RC. */ +#define TYPE_ASPEED_PCIE_CFG "aspeed.pcie-cfg" +#define TYPE_ASPEED_2700_PCIE_CFG TYPE_ASPEED_PCIE_CFG "-ast2700" +OBJECT_DECLARE_TYPE(AspeedPCIECfgState, AspeedPCIECfgClass, ASPEED_PCIE_CFG); + +struct AspeedPCIECfgState { + SysBusDevice parent_obj; + + MemoryRegion mmio; + uint32_t *regs; + uint32_t id; + + const AspeedPCIERcRegs *rc_regs; + AspeedPCIERcState rc; + uint32_t tlpn_fifo[3]; + uint32_t tlpn_idx; +}; + +struct AspeedPCIECfgClass { + SysBusDeviceClass parent_class; + + const AspeedPCIERegMap *reg_map; + const MemoryRegionOps *reg_ops; + + uint32_t rc_msi_addr; + uint32_t rc_rp_addr; + uint64_t rc_bus_nr; + uint64_t nr_regs; + bool rc_has_rd; +}; + +#define TYPE_ASPEED_PCIE_PHY "aspeed.pcie-phy" +#define TYPE_ASPEED_2700_PCIE_PHY TYPE_ASPEED_PCIE_PHY "-ast2700" +OBJECT_DECLARE_TYPE(AspeedPCIEPhyState, AspeedPCIEPhyClass, ASPEED_PCIE_PHY); + +struct AspeedPCIEPhyState { + SysBusDevice parent_obj; + + MemoryRegion mmio; + uint32_t *regs; + uint32_t id; +}; + +struct AspeedPCIEPhyClass { + SysBusDeviceClass parent_class; + + uint64_t nr_regs; +}; + +#endif /* ASPEED_PCIE_H */ diff --git a/include/hw/pci-host/gpex.h b/include/hw/pci-host/gpex.h index 8447153..feaf827 100644 --- a/include/hw/pci-host/gpex.h +++ b/include/hw/pci-host/gpex.h @@ -45,6 +45,7 @@ struct GPEXConfig { MemMapEntry pio; int irq; PCIBus *bus; + bool pci_native_hotplug; }; typedef struct GPEXIrq GPEXIrq; diff --git a/include/hw/pci-host/ls7a.h b/include/hw/pci-host/ls7a.h index 79d4ea8..33e7942 100644 --- a/include/hw/pci-host/ls7a.h +++ b/include/hw/pci-host/ls7a.h @@ -13,41 +13,4 @@ #include "qemu/range.h" #include "qom/object.h" -#define VIRT_PCI_MEM_BASE 0x40000000UL -#define VIRT_PCI_MEM_SIZE 0x40000000UL -#define VIRT_PCI_IO_OFFSET 0x4000 -#define VIRT_PCI_CFG_BASE 0x20000000 -#define VIRT_PCI_CFG_SIZE 0x08000000 -#define VIRT_PCI_IO_BASE 0x18004000UL -#define VIRT_PCI_IO_SIZE 0xC000 - -#define VIRT_PCH_REG_BASE 0x10000000UL -#define VIRT_IOAPIC_REG_BASE (VIRT_PCH_REG_BASE) -#define VIRT_PCH_MSI_ADDR_LOW 0x2FF00000UL -#define VIRT_PCH_REG_SIZE 0x400 -#define VIRT_PCH_MSI_SIZE 0x8 - -/* - * GSI_BASE is hard-coded with 64 in linux kernel, else kernel fails to boot - * 0 - 15 GSI for ISA devices even if there is no ISA devices - * 16 - 63 GSI for CPU devices such as timers/perf monitor etc - * 64 - GSI for external devices - */ -#define VIRT_PCH_PIC_IRQ_NUM 32 -#define VIRT_GSI_BASE 64 -#define VIRT_DEVICE_IRQS 16 -#define VIRT_UART_COUNT 4 -#define VIRT_UART_IRQ (VIRT_GSI_BASE + 2) -#define VIRT_UART_BASE 0x1fe001e0 -#define VIRT_UART_SIZE 0x100 -#define VIRT_RTC_IRQ (VIRT_GSI_BASE + 6) -#define VIRT_MISC_REG_BASE (VIRT_PCH_REG_BASE + 0x00080000) -#define VIRT_RTC_REG_BASE (VIRT_MISC_REG_BASE + 0x00050100) -#define VIRT_RTC_LEN 0x100 -#define VIRT_SCI_IRQ (VIRT_GSI_BASE + 7) - -#define VIRT_PLATFORM_BUS_BASEADDRESS 0x16000000 -#define VIRT_PLATFORM_BUS_SIZE 0x2000000 -#define VIRT_PLATFORM_BUS_NUM_IRQS 2 -#define VIRT_PLATFORM_BUS_IRQ (VIRT_GSI_BASE + 8) #endif diff --git a/include/hw/pci-host/pnv_phb3.h b/include/hw/pci-host/pnv_phb3.h index 24ca3dd..682f62a 100644 --- a/include/hw/pci-host/pnv_phb3.h +++ b/include/hw/pci-host/pnv_phb3.h @@ -14,7 +14,8 @@ #include "qom/object.h" #include "hw/pci-host/pnv_phb.h" -typedef struct PnvPHB3 PnvPHB3; +#define TYPE_PNV_PHB3 "pnv-phb3" +OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB3, PNV_PHB3) /* * PHB3 XICS Source for MSIs @@ -115,9 +116,6 @@ OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB3RootBus, PNV_PHB3_ROOT_BUS) /* * PHB3 PCIe Host Bridge for PowerNV machines (POWER8) */ -#define TYPE_PNV_PHB3 "pnv-phb3" -OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB3, PNV_PHB3) - #define PNV_PHB3_NUM_M64 16 #define PNV_PHB3_NUM_REGS (0x1000 >> 3) #define PNV_PHB3_NUM_LSI 8 diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index 8a80c0c..de996e7 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -17,8 +17,11 @@ #include "hw/ppc/xive.h" #include "qom/object.h" + +#define TYPE_PNV_PHB4 "pnv-phb4" +OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB4, PNV_PHB4) + typedef struct PnvPhb4PecStack PnvPhb4PecStack; -typedef struct PnvPHB4 PnvPHB4; /* * We have one such address space wrapper per possible device under @@ -59,9 +62,6 @@ OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB4RootBus, PNV_PHB4_ROOT_BUS) /* * PHB4 PCIe Host Bridge for PowerNV machines (POWER9) */ -#define TYPE_PNV_PHB4 "pnv-phb4" -OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB4, PNV_PHB4) - #define PNV_PHB4_MAX_LSIs 8 #define PNV_PHB4_MAX_INTs 4096 #define PNV_PHB4_MAX_MIST (PNV_PHB4_MAX_INTs >> 2) diff --git a/include/hw/pci/msix.h b/include/hw/pci/msix.h index 0e6f257..551a2bc 100644 --- a/include/hw/pci/msix.h +++ b/include/hw/pci/msix.h @@ -7,12 +7,12 @@ void msix_set_message(PCIDevice *dev, int vector, MSIMessage msg); MSIMessage msix_get_message(PCIDevice *dev, unsigned int vector); -int msix_init(PCIDevice *dev, unsigned short nentries, +int msix_init(PCIDevice *dev, uint32_t nentries, MemoryRegion *table_bar, uint8_t table_bar_nr, unsigned table_offset, MemoryRegion *pba_bar, uint8_t pba_bar_nr, unsigned pba_offset, uint8_t cap_pos, Error **errp); -int msix_init_exclusive_bar(PCIDevice *dev, unsigned short nentries, +int msix_init_exclusive_bar(PCIDevice *dev, uint32_t nentries, uint8_t bar_nr, Error **errp); void msix_write_config(PCIDevice *dev, uint32_t address, uint32_t val, int len); @@ -32,6 +32,7 @@ int msix_present(PCIDevice *dev); bool msix_is_masked(PCIDevice *dev, unsigned vector); void msix_set_pending(PCIDevice *dev, unsigned vector); void msix_clr_pending(PCIDevice *dev, int vector); +int msix_is_pending(PCIDevice *dev, unsigned vector); void msix_vector_use(PCIDevice *dev, unsigned vector); void msix_vector_unuse(PCIDevice *dev, unsigned vector); diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index c2fe6ca..b72e484 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -134,6 +134,15 @@ struct PCIHostDeviceAddress { unsigned int function; }; +/* + * Represents the Address Type (AT) field in a PCI request, + * see MemTxAttrs.address_type + */ +typedef enum PCIAddressType { + PCI_AT_UNTRANSLATED = 0, /* Default when no attribute is set */ + PCI_AT_TRANSLATED = 1, +} PCIAddressType; + typedef void PCIConfigWriteFunc(PCIDevice *pci_dev, uint32_t address, uint32_t data, int len); typedef uint32_t PCIConfigReadFunc(PCIDevice *pci_dev, @@ -222,6 +231,8 @@ enum { QEMU_PCIE_EXT_TAG = (1 << QEMU_PCIE_EXT_TAG_BITNR), #define QEMU_PCI_CAP_PM_BITNR 14 QEMU_PCI_CAP_PM = (1 << QEMU_PCI_CAP_PM_BITNR), +#define QEMU_PCI_SKIP_RESET_ON_CPR_BITNR 15 + QEMU_PCI_SKIP_RESET_ON_CPR = (1 << QEMU_PCI_SKIP_RESET_ON_CPR_BITNR), }; typedef struct PCIINTxRoute { @@ -375,6 +386,28 @@ void pci_bus_get_w64_range(PCIBus *bus, Range *range); void pci_device_deassert_intx(PCIDevice *dev); +/* Page Request Interface */ +typedef enum { + IOMMU_PRI_RESP_SUCCESS, + IOMMU_PRI_RESP_INVALID_REQUEST, + IOMMU_PRI_RESP_FAILURE, +} IOMMUPRIResponseCode; + +typedef struct IOMMUPRIResponse { + IOMMUPRIResponseCode response_code; + uint16_t prgi; +} IOMMUPRIResponse; + +struct IOMMUPRINotifier; + +typedef void (*IOMMUPRINotify)(struct IOMMUPRINotifier *notifier, + IOMMUPRIResponse *response); + +typedef struct IOMMUPRINotifier { + IOMMUPRINotify notify; +} IOMMUPRINotifier; + +#define PCI_PRI_PRGI_MASK 0x1ffU /** * struct PCIIOMMUOps: callbacks structure for specific IOMMU handlers @@ -429,6 +462,179 @@ typedef struct PCIIOMMUOps { * @devfn: device and function number of the PCI device. */ void (*unset_iommu_device)(PCIBus *bus, void *opaque, int devfn); + /** + * @get_iotlb_info: get properties required to initialize a device IOTLB. + * + * Callback required if devices are allowed to cache translations. + * + * @opaque: the data passed to pci_setup_iommu(). + * + * @addr_width: the address width of the IOMMU (output parameter). + * + * @min_page_size: the page size of the IOMMU (output parameter). + */ + void (*get_iotlb_info)(void *opaque, uint8_t *addr_width, + uint32_t *min_page_size); + /** + * @init_iotlb_notifier: initialize an IOMMU notifier. + * + * Optional callback. + * + * @bus: the #PCIBus of the PCI device. + * + * @opaque: the data passed to pci_setup_iommu(). + * + * @devfn: device and function number of the PCI device. + * + * @n: the notifier to be initialized. + * + * @fn: the callback to be installed. + * + * @user_opaque: a user pointer that can be used to track a state. + */ + void (*init_iotlb_notifier)(PCIBus *bus, void *opaque, int devfn, + IOMMUNotifier *n, IOMMUNotify fn, + void *user_opaque); + /** + * @register_iotlb_notifier: setup an IOTLB invalidation notifier. + * + * Callback required if devices are allowed to cache translations. + * + * @bus: the #PCIBus of the PCI device. + * + * @opaque: the data passed to pci_setup_iommu(). + * + * @devfn: device and function number of the PCI device. + * + * @pasid: the pasid of the address space to watch. + * + * @n: the notifier to register. + */ + void (*register_iotlb_notifier)(PCIBus *bus, void *opaque, int devfn, + uint32_t pasid, IOMMUNotifier *n); + /** + * @unregister_iotlb_notifier: remove an IOTLB invalidation notifier. + * + * Callback required if devices are allowed to cache translations. + * + * @bus: the #PCIBus of the PCI device. + * + * @opaque: the data passed to pci_setup_iommu(). + * + * @devfn: device and function number of the PCI device. + * + * @pasid: the pasid of the address space to stop watching. + * + * @n: the notifier to unregister. + */ + void (*unregister_iotlb_notifier)(PCIBus *bus, void *opaque, int devfn, + uint32_t pasid, IOMMUNotifier *n); + /** + * @ats_request_translation: issue an ATS request. + * + * Callback required if devices are allowed to use the address + * translation service. + * + * @bus: the #PCIBus of the PCI device. + * + * @opaque: the data passed to pci_setup_iommu(). + * + * @devfn: device and function number of the PCI device. + * + * @pasid: the pasid of the address space to use for the request. + * + * @priv_req: privileged mode bit (PASID TLP). + * + * @exec_req: execute request bit (PASID TLP). + * + * @addr: start address of the memory range to be translated. + * + * @length: length of the memory range in bytes. + * + * @no_write: request a read-only translation (if supported). + * + * @result: buffer in which the TLB entries will be stored. + * + * @result_length: result buffer length. + * + * @err_count: number of untranslated subregions. + * + * Returns: the number of translations stored in the result buffer, or + * -ENOMEM if the buffer is not large enough. + */ + ssize_t (*ats_request_translation)(PCIBus *bus, void *opaque, int devfn, + uint32_t pasid, bool priv_req, + bool exec_req, hwaddr addr, + size_t length, bool no_write, + IOMMUTLBEntry *result, + size_t result_length, + uint32_t *err_count); + /** + * @pri_register_notifier: setup the PRI completion callback. + * + * Callback required if devices are allowed to use the page request + * interface. + * + * @bus: the #PCIBus of the PCI device. + * + * @opaque: the data passed to pci_setup_iommu(). + * + * @devfn: device and function number of the PCI device. + * + * @pasid: the pasid of the address space to track. + * + * @notifier: the notifier to register. + */ + void (*pri_register_notifier)(PCIBus *bus, void *opaque, int devfn, + uint32_t pasid, IOMMUPRINotifier *notifier); + /** + * @pri_unregister_notifier: remove the PRI completion callback. + * + * Callback required if devices are allowed to use the page request + * interface. + * + * @bus: the #PCIBus of the PCI device. + * + * @opaque: the data passed to pci_setup_iommu(). + * + * @devfn: device and function number of the PCI device. + * + * @pasid: the pasid of the address space to stop tracking. + */ + void (*pri_unregister_notifier)(PCIBus *bus, void *opaque, int devfn, + uint32_t pasid); + /** + * @pri_request_page: issue a PRI request. + * + * Callback required if devices are allowed to use the page request + * interface. + * + * @bus: the #PCIBus of the PCI device. + * + * @opaque: the data passed to pci_setup_iommu(). + * + * @devfn: device and function number of the PCI device. + * + * @pasid: the pasid of the address space to use for the request. + * + * @priv_req: privileged mode bit (PASID TLP). + * + * @exec_req: execute request bit (PASID TLP). + * + * @addr: untranslated address of the requested page. + * + * @lpig: last page in group. + * + * @prgi: page request group index. + * + * @is_read: request read access. + * + * @is_write: request write access. + */ + int (*pri_request_page)(PCIBus *bus, void *opaque, int devfn, + uint32_t pasid, bool priv_req, bool exec_req, + hwaddr addr, bool lpig, uint16_t prgi, bool is_read, + bool is_write); } PCIIOMMUOps; AddressSpace *pci_device_iommu_address_space(PCIDevice *dev); @@ -437,6 +643,126 @@ bool pci_device_set_iommu_device(PCIDevice *dev, HostIOMMUDevice *hiod, void pci_device_unset_iommu_device(PCIDevice *dev); /** + * pci_iommu_get_iotlb_info: get properties required to initialize a + * device IOTLB. + * + * Returns 0 on success, or a negative errno otherwise. + * + * @dev: the device that wants to get the information. + * @addr_width: the address width of the IOMMU (output parameter). + * @min_page_size: the page size of the IOMMU (output parameter). + */ +int pci_iommu_get_iotlb_info(PCIDevice *dev, uint8_t *addr_width, + uint32_t *min_page_size); + +/** + * pci_iommu_init_iotlb_notifier: initialize an IOMMU notifier. + * + * This function is used by devices before registering an IOTLB notifier. + * + * @dev: the device. + * @n: the notifier to be initialized. + * @fn: the callback to be installed. + * @opaque: a user pointer that can be used to track a state. + */ +int pci_iommu_init_iotlb_notifier(PCIDevice *dev, IOMMUNotifier *n, + IOMMUNotify fn, void *opaque); + +/** + * pci_ats_request_translation: perform an ATS request. + * + * Returns the number of translations stored in @result in case of success, + * a negative error code otherwise. + * -ENOMEM is returned when the result buffer is not large enough to store + * all the translations. + * + * @dev: the ATS-capable PCI device. + * @pasid: the pasid of the address space in which the translation will be done. + * @priv_req: privileged mode bit (PASID TLP). + * @exec_req: execute request bit (PASID TLP). + * @addr: start address of the memory range to be translated. + * @length: length of the memory range in bytes. + * @no_write: request a read-only translation (if supported). + * @result: buffer in which the TLB entries will be stored. + * @result_length: result buffer length. + * @err_count: number of untranslated subregions. + */ +ssize_t pci_ats_request_translation(PCIDevice *dev, uint32_t pasid, + bool priv_req, bool exec_req, + hwaddr addr, size_t length, + bool no_write, IOMMUTLBEntry *result, + size_t result_length, + uint32_t *err_count); + +/** + * pci_pri_request_page: perform a PRI request. + * + * Returns 0 if the PRI request has been sent to the guest OS, + * an error code otherwise. + * + * @dev: the PRI-capable PCI device. + * @pasid: the pasid of the address space in which the translation will be done. + * @priv_req: privileged mode bit (PASID TLP). + * @exec_req: execute request bit (PASID TLP). + * @addr: untranslated address of the requested page. + * @lpig: last page in group. + * @prgi: page request group index. + * @is_read: request read access. + * @is_write: request write access. + */ +int pci_pri_request_page(PCIDevice *dev, uint32_t pasid, bool priv_req, + bool exec_req, hwaddr addr, bool lpig, + uint16_t prgi, bool is_read, bool is_write); + +/** + * pci_pri_register_notifier: register the PRI callback for a given address + * space. + * + * Returns 0 on success, an error code otherwise. + * + * @dev: the PRI-capable PCI device. + * @pasid: the pasid of the address space to track. + * @notifier: the notifier to register. + */ +int pci_pri_register_notifier(PCIDevice *dev, uint32_t pasid, + IOMMUPRINotifier *notifier); + +/** + * pci_pri_unregister_notifier: remove the PRI callback from a given address + * space. + * + * @dev: the PRI-capable PCI device. + * @pasid: the pasid of the address space to stop tracking. + */ +void pci_pri_unregister_notifier(PCIDevice *dev, uint32_t pasid); + +/** + * pci_iommu_register_iotlb_notifier: register a notifier for changes to + * IOMMU translation entries in a specific address space. + * + * Returns 0 on success, or a negative errno otherwise. + * + * @dev: the device that wants to get notified. + * @pasid: the pasid of the address space to track. + * @n: the notifier to register. + */ +int pci_iommu_register_iotlb_notifier(PCIDevice *dev, uint32_t pasid, + IOMMUNotifier *n); + +/** + * pci_iommu_unregister_iotlb_notifier: unregister a notifier that has been + * registered with pci_iommu_register_iotlb_notifier. + * + * Returns 0 on success, or a negative errno otherwise. + * + * @dev: the device that wants to stop notifications. + * @pasid: the pasid of the address space to stop tracking. + * @n: the notifier to unregister. + */ +int pci_iommu_unregister_iotlb_notifier(PCIDevice *dev, uint32_t pasid, + IOMMUNotifier *n); + +/** * pci_setup_iommu: Initialize specific IOMMU handlers for a PCIBus * * Let PCI host bridges define specific operations. @@ -447,6 +773,8 @@ void pci_device_unset_iommu_device(PCIDevice *dev); */ void pci_setup_iommu(PCIBus *bus, const PCIIOMMUOps *ops, void *opaque); +void pci_setup_iommu_per_bus(PCIBus *bus, const PCIIOMMUOps *ops, void *opaque); + pcibus_t pci_bar_address(PCIDevice *d, int reg, uint8_t type, pcibus_t size); @@ -668,6 +996,7 @@ void lsi53c8xx_handle_legacy_cmdline(DeviceState *lsi_dev); qemu_irq pci_allocate_irq(PCIDevice *pci_dev); void pci_set_irq(PCIDevice *pci_dev, int level); +int pci_irq_disabled(PCIDevice *d); static inline void pci_irq_assert(PCIDevice *pci_dev) { diff --git a/include/hw/pci/pci_bridge.h b/include/hw/pci/pci_bridge.h index b0f5204..a055fd8 100644 --- a/include/hw/pci/pci_bridge.h +++ b/include/hw/pci/pci_bridge.h @@ -14,8 +14,8 @@ * 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, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * along with this program; if not, see + * <https://www.gnu.org/licenses/>. * * split out pci bus specific stuff from pci.[hc] to pci_bridge.[hc] * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp> @@ -104,6 +104,7 @@ typedef struct PXBPCIEDev { PXBDev parent_obj; } PXBPCIEDev; +#define TYPE_PXB_PCIE_BUS "pxb-pcie-bus" #define TYPE_PXB_CXL_BUS "pxb-cxl-bus" #define TYPE_PXB_DEV "pxb" OBJECT_DECLARE_SIMPLE_TYPE(PXBDev, PXB_DEV) diff --git a/include/hw/pci/pci_bus.h b/include/hw/pci/pci_bus.h index 2261312..c738446 100644 --- a/include/hw/pci/pci_bus.h +++ b/include/hw/pci/pci_bus.h @@ -35,6 +35,7 @@ struct PCIBus { enum PCIBusFlags flags; const PCIIOMMUOps *iommu_ops; void *iommu_opaque; + bool iommu_per_bus; uint8_t devfn_min; uint32_t slot_reserved_mask; pci_set_irq_fn set_irq; diff --git a/include/hw/pci/pci_device.h b/include/hw/pci/pci_device.h index e41d95b..88ccea5 100644 --- a/include/hw/pci/pci_device.h +++ b/include/hw/pci/pci_device.h @@ -4,6 +4,7 @@ #include "hw/pci/pci.h" #include "hw/pci/pcie.h" #include "hw/pci/pcie_doe.h" +#include "system/spdm-socket.h" #define TYPE_PCI_DEVICE "pci-device" typedef struct PCIDeviceClass PCIDeviceClass; @@ -90,6 +91,7 @@ struct PCIDevice { char name[64]; PCIIORegion io_regions[PCI_NUM_REGIONS]; AddressSpace bus_master_as; + bool is_master; MemoryRegion bus_master_container_region; MemoryRegion bus_master_enable_region; @@ -165,6 +167,7 @@ struct PCIDevice { /* SPDM */ uint16_t spdm_port; + SpdmTransportType spdm_trans; /* DOE */ DOECap doe_spdm; diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h index 33e2898..16034aa 100644 --- a/include/hw/pci/pci_ids.h +++ b/include/hw/pci/pci_ids.h @@ -291,4 +291,6 @@ #define PCI_VENDOR_ID_NVIDIA 0x10de +#define PCI_VENDOR_ID_ASPEED 0x1A03 + #endif diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h index 70a5de0..42cebcd 100644 --- a/include/hw/pci/pcie.h +++ b/include/hw/pci/pcie.h @@ -70,8 +70,10 @@ struct PCIExpressDevice { uint16_t aer_cap; PCIEAERLog aer_log; - /* Offset of ATS capability in config space */ + /* Offset of ATS, PRI and PASID capabilities in config space */ uint16_t ats_cap; + uint16_t pasid_cap; + uint16_t pri_cap; /* ACS */ uint16_t acs_cap; @@ -150,4 +152,14 @@ void pcie_cap_slot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp); void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp); + +void pcie_pasid_init(PCIDevice *dev, uint16_t offset, uint8_t pasid_width, + bool exec_perm, bool priv_mod); +void pcie_pri_init(PCIDevice *dev, uint16_t offset, uint32_t outstanding_pr_cap, + bool prg_response_pasid_req); + +uint32_t pcie_pri_get_req_alloc(const PCIDevice *dev); +bool pcie_pri_enabled(const PCIDevice *dev); +bool pcie_pasid_enabled(const PCIDevice *dev); +bool pcie_ats_enabled(const PCIDevice *dev); #endif /* QEMU_PCIE_H */ diff --git a/include/hw/pci/pcie_regs.h b/include/hw/pci/pcie_regs.h index 9d3b686..33a2222 100644 --- a/include/hw/pci/pcie_regs.h +++ b/include/hw/pci/pcie_regs.h @@ -86,6 +86,14 @@ typedef enum PCIExpLinkWidth { #define PCI_ARI_VER 1 #define PCI_ARI_SIZEOF 8 +/* PASID */ +#define PCI_PASID_VER 1 +#define PCI_EXT_CAP_PASID_MAX_WIDTH 20 +#define PCI_PASID_CAP_WIDTH_SHIFT 8 + +/* PRI */ +#define PCI_PRI_VER 1 + /* AER */ #define PCI_ERR_VER 2 #define PCI_ERR_SIZEOF 0x48 diff --git a/include/hw/pci/pcie_sriov.h b/include/hw/pci/pcie_sriov.h index aeaa38c..b0ea6a6 100644 --- a/include/hw/pci/pcie_sriov.h +++ b/include/hw/pci/pcie_sriov.h @@ -37,10 +37,6 @@ void pcie_sriov_pf_exit(PCIDevice *dev); void pcie_sriov_pf_init_vf_bar(PCIDevice *dev, int region_num, uint8_t type, dma_addr_t size); -/* Instantiate a bar for a VF */ -void pcie_sriov_vf_register_bar(PCIDevice *dev, int region_num, - MemoryRegion *memory); - /** * pcie_sriov_pf_init_from_user_created_vfs() - Initialize PF with user-created * VFs, adding ARI to PF diff --git a/include/hw/ppc/mac_dbdma.h b/include/hw/ppc/mac_dbdma.h index 896ee4a..7676488 100644 --- a/include/hw/ppc/mac_dbdma.h +++ b/include/hw/ppc/mac_dbdma.h @@ -164,7 +164,9 @@ struct DBDMAState { DBDMA_channel channels[DBDMA_CHANNELS]; QEMUBH *bh; }; -typedef struct DBDMAState DBDMAState; + +#define TYPE_MAC_DBDMA "mac-dbdma" +OBJECT_DECLARE_SIMPLE_TYPE(DBDMAState, MAC_DBDMA) /* Externally callable functions */ @@ -173,7 +175,4 @@ void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq, void *opaque); void DBDMA_kick(DBDMAState *dbdma); -#define TYPE_MAC_DBDMA "mac-dbdma" -OBJECT_DECLARE_SIMPLE_TYPE(DBDMAState, MAC_DBDMA) - #endif diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h index d8fca07..cbdddfc 100644 --- a/include/hw/ppc/pnv.h +++ b/include/hw/ppc/pnv.h @@ -33,6 +33,7 @@ typedef struct PnvChip PnvChip; typedef struct Pnv8Chip Pnv8Chip; typedef struct Pnv9Chip Pnv9Chip; typedef struct Pnv10Chip Pnv10Chip; +typedef struct Pnv10Chip Pnv11Chip; #define PNV_CHIP_TYPE_SUFFIX "-" TYPE_PNV_CHIP #define PNV_CHIP_TYPE_NAME(cpu_model) cpu_model PNV_CHIP_TYPE_SUFFIX @@ -57,6 +58,10 @@ DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER9, DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER10, TYPE_PNV_CHIP_POWER10) +#define TYPE_PNV_CHIP_POWER11 PNV_CHIP_TYPE_NAME("power11_v2.0") +DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER11, + TYPE_PNV_CHIP_POWER11) + PnvCore *pnv_chip_find_core(PnvChip *chip, uint32_t core_id); PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir); @@ -252,4 +257,37 @@ void pnv_bmc_set_pnor(IPMIBmc *bmc, PnvPnor *pnor); #define PNV10_HOMER_BASE(chip) \ (0x300ffd800000ll + ((uint64_t)(chip)->chip_id) * PNV_HOMER_SIZE) +/* Power11 */ +#define PNV11_XSCOM_SIZE PNV10_XSCOM_SIZE +#define PNV11_XSCOM_BASE(chip) PNV10_XSCOM_BASE(chip) + +#define PNV11_LPCM_SIZE PNV10_LPCM_SIZE +#define PNV11_LPCM_BASE(chip) PNV10_LPCM_BASE(chip) + +#define PNV11_PSIHB_ESB_SIZE PNV10_PSIHB_ESB_SIZE +#define PNV11_PSIHB_ESB_BASE(chip) PNV10_PSIHB_ESB_BASE(chip) + +#define PNV11_PSIHB_SIZE PNV10_PSIHB_SIZE +#define PNV11_PSIHB_BASE(chip) PNV10_PSIHB_BASE(chip) + +#define PNV11_XIVE2_IC_SIZE PNV10_XIVE2_IC_SIZE +#define PNV11_XIVE2_IC_BASE(chip) PNV10_XIVE2_IC_BASE(chip) + +#define PNV11_XIVE2_TM_SIZE PNV10_XIVE2_TM_SIZE +#define PNV11_XIVE2_TM_BASE(chip) PNV10_XIVE2_TM_BASE(chip) + +#define PNV11_XIVE2_NVC_SIZE PNV10_XIVE2_NVC_SIZE +#define PNV11_XIVE2_NVC_BASE(chip) PNV10_XIVE2_NVC_BASE(chip) + +#define PNV11_XIVE2_NVPG_SIZE PNV10_XIVE2_NVPG_SIZE +#define PNV11_XIVE2_NVPG_BASE(chip) PNV10_XIVE2_NVPG_BASE(chip) + +#define PNV11_XIVE2_ESB_SIZE PNV10_XIVE2_ESB_SIZE +#define PNV11_XIVE2_ESB_BASE(chip) PNV10_XIVE2_ESB_BASE(chip) + +#define PNV11_XIVE2_END_SIZE PNV10_XIVE2_END_SIZE +#define PNV11_XIVE2_END_BASE(chip) PNV10_XIVE2_END_BASE(chip) + +#define PNV11_OCC_SENSOR_BASE(chip) PNV10_OCC_SENSOR_BASE(chip) + #endif /* PPC_PNV_H */ diff --git a/include/hw/ppc/pnv_chip.h b/include/hw/ppc/pnv_chip.h index 24ce37a..a5b8c49 100644 --- a/include/hw/ppc/pnv_chip.h +++ b/include/hw/ppc/pnv_chip.h @@ -141,6 +141,13 @@ struct Pnv10Chip { #define PNV10_PIR2CHIP(pir) (((pir) >> 8) & 0x7f) #define PNV10_PIR2THREAD(pir) (((pir) & 0x7f)) +#define TYPE_PNV11_CHIP "pnv11-chip" +DECLARE_INSTANCE_CHECKER(Pnv11Chip, PNV11_CHIP, + TYPE_PNV11_CHIP) + +/* Power11 core is same as Power10 */ +typedef struct Pnv10Chip Pnv11Chip; + struct PnvChipClass { /*< private >*/ SysBusDeviceClass parent_class; @@ -163,6 +170,7 @@ struct PnvChipClass { void (*intc_reset)(PnvChip *chip, PowerPCCPU *cpu); void (*intc_destroy)(PnvChip *chip, PowerPCCPU *cpu); void (*intc_print_info)(PnvChip *chip, PowerPCCPU *cpu, GString *buf); + void* (*intc_get)(PnvChip *chip); ISABus *(*isa_create)(PnvChip *chip, Error **errp); void (*dt_populate)(PnvChip *chip, void *fdt); void (*pic_print_info)(PnvChip *chip, GString *buf); diff --git a/include/hw/ppc/pnv_chiptod.h b/include/hw/ppc/pnv_chiptod.h index fde569b..466b065 100644 --- a/include/hw/ppc/pnv_chiptod.h +++ b/include/hw/ppc/pnv_chiptod.h @@ -17,6 +17,8 @@ OBJECT_DECLARE_TYPE(PnvChipTOD, PnvChipTODClass, PNV_CHIPTOD) DECLARE_INSTANCE_CHECKER(PnvChipTOD, PNV9_CHIPTOD, TYPE_PNV9_CHIPTOD) #define TYPE_PNV10_CHIPTOD TYPE_PNV_CHIPTOD "-POWER10" DECLARE_INSTANCE_CHECKER(PnvChipTOD, PNV10_CHIPTOD, TYPE_PNV10_CHIPTOD) +#define TYPE_PNV11_CHIPTOD TYPE_PNV_CHIPTOD "-POWER11" +DECLARE_INSTANCE_CHECKER(PnvChipTOD, PNV11_CHIPTOD, TYPE_PNV11_CHIPTOD) enum tod_state { tod_error = 0, diff --git a/include/hw/ppc/pnv_xscom.h b/include/hw/ppc/pnv_xscom.h index b14549d..610b075 100644 --- a/include/hw/ppc/pnv_xscom.h +++ b/include/hw/ppc/pnv_xscom.h @@ -207,6 +207,55 @@ struct PnvXScomInterfaceClass { #define PNV10_XSCOM_PIB_SPIC_BASE 0xc0000 #define PNV10_XSCOM_PIB_SPIC_SIZE 0x20 +/* + * Power11 core is same as Power10 + */ +#define PNV11_XSCOM_EC_BASE(core) PNV10_XSCOM_EC_BASE(core) + +#define PNV11_XSCOM_ADU_BASE PNV10_XSCOM_ADU_BASE +#define PNV11_XSCOM_ADU_SIZE PNV10_XSCOM_ADU_SIZE + +#define PNV11_XSCOM_QME_BASE(core) PNV10_XSCOM_QME_BASE(core) + +#define PNV11_XSCOM_EQ_BASE(core) PNV10_XSCOM_EQ_BASE(core) + +#define PNV11_XSCOM_PSIHB_BASE PNV10_XSCOM_PSIHB_BASE +#define PNV11_XSCOM_PSIHB_SIZE PNV10_XSCOM_PSIHB_SIZE + +#define PNV11_XSCOM_I2CM_BASE PNV10_XSCOM_I2CM_BASE +#define PNV11_XSCOM_I2CM_SIZE PNV10_XSCOM_I2CM_SIZE + +#define PNV11_XSCOM_CHIPTOD_BASE PNV10_XSCOM_CHIPTOD_BASE +#define PNV11_XSCOM_CHIPTOD_SIZE PNV10_XSCOM_CHIPTOD_SIZE + +#define PNV11_XSCOM_OCC_BASE PNV10_XSCOM_OCC_BASE +#define PNV11_XSCOM_OCC_SIZE PNV10_XSCOM_OCC_SIZE + +#define PNV11_XSCOM_SBE_CTRL_BASE PNV10_XSCOM_SBE_CTRL_BASE +#define PNV11_XSCOM_SBE_CTRL_SIZE PNV10_XSCOM_SBE_CTRL_SIZE + +#define PNV11_XSCOM_SBE_MBOX_BASE PNV10_XSCOM_SBE_MBOX_BASE +#define PNV11_XSCOM_SBE_MBOX_SIZE PNV10_XSCOM_SBE_MBOX_SIZE + +#define PNV11_XSCOM_PBA_BASE PNV10_XSCOM_PBA_BASE +#define PNV11_XSCOM_PBA_SIZE PNV10_XSCOM_PBA_SIZE + +#define PNV11_XSCOM_XIVE2_BASE PNV10_XSCOM_XIVE2_BASE +#define PNV11_XSCOM_XIVE2_SIZE PNV10_XSCOM_XIVE2_SIZE + +#define PNV11_XSCOM_N1_CHIPLET_CTRL_REGS_BASE \ + PNV10_XSCOM_N1_CHIPLET_CTRL_REGS_BASE +#define PNV11_XSCOM_CHIPLET_CTRL_REGS_SIZE PNV10_XSCOM_CHIPLET_CTRL_REGS_SIZE + +#define PNV11_XSCOM_N1_PB_SCOM_EQ_BASE PNV10_XSCOM_N1_PB_SCOM_EQ_BASE +#define PNV11_XSCOM_N1_PB_SCOM_EQ_SIZE PNV10_XSCOM_N1_PB_SCOM_EQ_SIZE + +#define PNV11_XSCOM_N1_PB_SCOM_ES_BASE PNV10_XSCOM_N1_PB_SCOM_ES_BASE +#define PNV11_XSCOM_N1_PB_SCOM_ES_SIZE PNV10_XSCOM_N1_PB_SCOM_ES_SIZE + +#define PNV11_XSCOM_PIB_SPIC_BASE PNV10_XSCOM_PIB_SPIC_BASE +#define PNV11_XSCOM_PIB_SPIC_SIZE PNV10_XSCOM_PIB_SPIC_SIZE + void pnv_xscom_init(PnvChip *chip, uint64_t size, hwaddr addr); int pnv_dt_xscom(PnvChip *chip, void *fdt, int root_offset, uint64_t xscom_base, uint64_t xscom_size, diff --git a/include/hw/ppc/ppc.h b/include/hw/ppc/ppc.h index 8a14d62..cb51d70 100644 --- a/include/hw/ppc/ppc.h +++ b/include/hw/ppc/ppc.h @@ -52,6 +52,7 @@ struct ppc_tb_t { #define PPC_DECR_UNDERFLOW_LEVEL (1 << 4) /* Decr interrupt active when * the most significant bit is 1. */ +#define PPC_TIMER_PPE (1 << 5) /* Enable PPE support */ uint64_t cpu_ppc_get_tb(ppc_tb_t *tb_env, uint64_t vmclk, int64_t tb_offset); void cpu_ppc_tb_init(CPUPPCState *env, uint32_t freq); diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 39bd5bd..28cf272 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -13,6 +13,7 @@ #include "hw/ppc/xics.h" /* For ICSState */ #include "hw/ppc/spapr_tpm_proxy.h" #include "hw/ppc/spapr_nested.h" /* For SpaprMachineStateNested */ +#include "hw/ppc/spapr_fadump.h" /* For FadumpMemStruct */ struct SpaprVioBus; struct SpaprPhbState; @@ -139,27 +140,11 @@ struct SpaprCapabilities { * SpaprMachineClass: */ struct SpaprMachineClass { - /*< private >*/ MachineClass parent_class; - /*< public >*/ - bool dr_phb_enabled; /* enable dynamic-reconfig/hotplug of PHBs */ - bool update_dt_enabled; /* enable KVMPPC_H_UPDATE_DT */ - bool legacy_irq_allocation; - uint32_t nr_xirqs; - bool broken_host_serial_model; /* present real host info to the guest */ - bool pre_4_1_migration; /* don't migrate hpt-max-page-size */ - bool linux_pci_probe; - bool smp_threads_vsmt; /* set VSMT to smp_threads by default */ - hwaddr rma_limit; /* clamp the RMA to this size */ bool pre_5_1_assoc_refpoints; bool pre_5_2_numa_associativity; bool pre_6_2_numa_affinity; - - bool (*phb_placement)(SpaprMachineState *spapr, uint32_t index, - uint64_t *buid, hwaddr *pio, - hwaddr *mmio32, hwaddr *mmio64, - unsigned n_dma, uint32_t *liobns, Error **errp); SpaprResizeHpt resize_hpt_default; SpaprCapabilities default_caps; SpaprIrq *irq; @@ -283,6 +268,11 @@ struct SpaprMachineState { Error *fwnmi_migration_blocker; SpaprWatchdog wds[WDT_MAX_WATCHDOGS]; + + /* Fadump State */ + bool fadump_registered; + bool fadump_dump_active; + FadumpMemStruct registered_fdm; }; #define H_SUCCESS 0 @@ -708,6 +698,8 @@ void push_sregs_to_kvm_pr(SpaprMachineState *spapr); #define RTAS_OUT_PARAM_ERROR -3 #define RTAS_OUT_NOT_SUPPORTED -3 #define RTAS_OUT_NO_SUCH_INDICATOR -3 +#define RTAS_OUT_DUMP_ALREADY_REGISTERED -9 +#define RTAS_OUT_DUMP_ACTIVE -10 #define RTAS_OUT_NOT_AUTHORIZED -9002 #define RTAS_OUT_SYSPARM_PARAM_ERROR -9999 @@ -770,8 +762,9 @@ void push_sregs_to_kvm_pr(SpaprMachineState *spapr); #define RTAS_IBM_SUSPEND_ME (RTAS_TOKEN_BASE + 0x2A) #define RTAS_IBM_NMI_REGISTER (RTAS_TOKEN_BASE + 0x2B) #define RTAS_IBM_NMI_INTERLOCK (RTAS_TOKEN_BASE + 0x2C) +#define RTAS_CONFIGURE_KERNEL_DUMP (RTAS_TOKEN_BASE + 0x2D) -#define RTAS_TOKEN_MAX (RTAS_TOKEN_BASE + 0x2D) +#define RTAS_TOKEN_MAX (RTAS_TOKEN_BASE + 0x2E) /* RTAS ibm,get-system-parameter token values */ #define RTAS_SYSPARM_SPLPAR_CHARACTERISTICS 20 diff --git a/include/hw/ppc/spapr_fadump.h b/include/hw/ppc/spapr_fadump.h new file mode 100644 index 0000000..fde2830 --- /dev/null +++ b/include/hw/ppc/spapr_fadump.h @@ -0,0 +1,124 @@ +/* + * Firmware Assisted Dump in PSeries + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef PPC_SPAPR_FADUMP_H +#define PPC_SPAPR_FADUMP_H + +#include "qemu/osdep.h" +#include "cpu.h" + +/* Fadump commands */ +#define FADUMP_CMD_REGISTER 1 +#define FADUMP_CMD_UNREGISTER 2 +#define FADUMP_CMD_INVALIDATE 3 + +#define FADUMP_VERSION 1 + +/* Firmware provided dump sections */ +#define FADUMP_CPU_STATE_DATA 0x0001 +#define FADUMP_HPTE_REGION 0x0002 +#define FADUMP_REAL_MODE_REGION 0x0011 + +/* OS defined sections */ +#define FADUMP_PARAM_AREA 0x0100 + +/* Dump request flag */ +#define FADUMP_REQUEST_FLAG 0x00000001 + +/* Dump status flags */ +#define FADUMP_STATUS_DUMP_PERFORMED 0x8000 +#define FADUMP_STATUS_DUMP_TRIGGERED 0x4000 +#define FADUMP_STATUS_DUMP_ERROR 0x2000 + +/* Region dump error flags */ +#define FADUMP_ERROR_INVALID_DATA_TYPE 0x8000 +#define FADUMP_ERROR_INVALID_SOURCE_ADDR 0x4000 +#define FADUMP_ERROR_LENGTH_EXCEEDS_SOURCE 0x2000 +#define FADUMP_ERROR_INVALID_DEST_ADDR 0x1000 +#define FAUDMP_ERROR_DEST_TOO_SMALL 0x0800 + +/* + * The Firmware Assisted Dump Memory structure supports a maximum of 10 sections + * in the dump memory structure. Presently, three sections are used for + * CPU state data, HPTE & Parameters area, while the remaining seven sections + * can be used for boot memory regions. + */ +#define FADUMP_MAX_SECTIONS 10 + +/* Number of register entries stored per cpu */ +#define FADUMP_PER_CPU_REG_ENTRIES (32 /*GPR*/ + 45 /*others*/ + 2 /*STRT & END*/) + +/* Mask of CPU ID in CPUSTRT and CPUEND entries */ +#define FADUMP_CPU_ID_MASK ((1ULL << 32) - 1) + +typedef struct FadumpSection FadumpSection; +typedef struct FadumpSectionHeader FadumpSectionHeader; +typedef struct FadumpMemStruct FadumpMemStruct; +typedef struct FadumpRegSaveAreaHeader FadumpRegSaveAreaHeader; +typedef struct FadumpRegEntry FadumpRegEntry; + +struct SpaprMachineState; + +/* Kernel Dump section info */ +/* All fields are in big-endian */ +struct FadumpSection { + uint32_t request_flag; + uint16_t source_data_type; + uint16_t error_flags; + uint64_t source_address; + uint64_t source_len; + uint64_t bytes_dumped; + uint64_t destination_address; +}; + +/* ibm,configure-kernel-dump header. */ +struct FadumpSectionHeader { + uint32_t dump_format_version; + uint16_t dump_num_sections; + uint16_t dump_status_flag; + uint32_t offset_first_dump_section; + + /* Fields for disk dump option. */ + uint32_t dd_block_size; + uint64_t dd_block_offset; + uint64_t dd_num_blocks; + uint32_t dd_offset_disk_path; + + /* Maximum time allowed to prevent an automatic dump-reboot. */ + uint32_t max_time_auto; +}; + +/* Note: All the data in these structures is in big-endian */ +struct FadumpMemStruct { + FadumpSectionHeader header; + FadumpSection rgn[FADUMP_MAX_SECTIONS]; +}; + +/* + * The firmware-assisted dump format. + * + * The register save area is an area in the partition's memory used to preserve + * the register contents (CPU state data) for the active CPUs during a firmware + * assisted dump. The dump format contains register save area header followed + * by register entries. Each list of registers for a CPU starts with "CPUSTRT" + * and ends with "CPUEND". + */ + +/* Register save area header. */ +struct FadumpRegSaveAreaHeader { + uint64_t magic_number; + uint32_t version; + uint32_t num_cpu_offset; +}; + +/* Register entry. */ +struct FadumpRegEntry { + uint64_t reg_id; + uint64_t reg_value; +}; + +uint32_t do_fadump_register(struct SpaprMachineState *, target_ulong); +void trigger_fadump_boot(struct SpaprMachineState *, target_ulong); +#endif /* PPC_SPAPR_FADUMP_H */ diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h index cb9a85f..265d43e 100644 --- a/include/hw/ppc/spapr_irq.h +++ b/include/hw/ppc/spapr_irq.h @@ -40,6 +40,7 @@ #define SPAPR_IRQ_MSI (SPAPR_XIRQ_BASE + 0x0300) #define SPAPR_NR_XIRQS 0x1000 +#define SPAPR_IRQ_NR_MSIS (SPAPR_XIRQ_BASE + SPAPR_NR_XIRQS - SPAPR_IRQ_MSI) struct SpaprMachineState; @@ -89,7 +90,6 @@ void spapr_irq_print_info(struct SpaprMachineState *spapr, GString *buf); void spapr_irq_dt(struct SpaprMachineState *spapr, uint32_t nr_servers, void *fdt, uint32_t phandle); -uint32_t spapr_irq_nr_msis(struct SpaprMachineState *spapr); int spapr_irq_msi_alloc(struct SpaprMachineState *spapr, uint32_t num, bool align, Error **errp); void spapr_irq_msi_free(struct SpaprMachineState *spapr, int irq, uint32_t num); @@ -100,7 +100,6 @@ typedef struct SpaprIrq { } SpaprIrq; extern SpaprIrq spapr_irq_xics; -extern SpaprIrq spapr_irq_xics_legacy; extern SpaprIrq spapr_irq_xive; extern SpaprIrq spapr_irq_dual; diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h index 538f438..b7ca854 100644 --- a/include/hw/ppc/xive.h +++ b/include/hw/ppc/xive.h @@ -365,6 +365,11 @@ static inline uint32_t xive_tctx_word2(uint8_t *ring) return *((uint32_t *) &ring[TM_WORD2]); } +bool xive_ring_valid(XiveTCTX *tctx, uint8_t ring); +bool xive_nsr_indicates_exception(uint8_t ring, uint8_t nsr); +bool xive_nsr_indicates_group_exception(uint8_t ring, uint8_t nsr); +uint8_t xive_nsr_exception_ring(uint8_t ring, uint8_t nsr); + /* * XIVE Router */ @@ -421,6 +426,7 @@ void xive_router_end_notify(XiveRouter *xrtr, XiveEAS *eas); typedef struct XiveTCTXMatch { XiveTCTX *tctx; + int count; uint8_t ring; bool precluded; } XiveTCTXMatch; @@ -436,10 +442,10 @@ DECLARE_CLASS_CHECKERS(XivePresenterClass, XIVE_PRESENTER, struct XivePresenterClass { InterfaceClass parent; - int (*match_nvt)(XivePresenter *xptr, uint8_t format, - uint8_t nvt_blk, uint32_t nvt_idx, - bool crowd, bool cam_ignore, uint8_t priority, - uint32_t logic_serv, XiveTCTXMatch *match); + bool (*match_nvt)(XivePresenter *xptr, uint8_t format, + uint8_t nvt_blk, uint32_t nvt_idx, + bool crowd, bool cam_ignore, uint8_t priority, + uint32_t logic_serv, XiveTCTXMatch *match); bool (*in_kernel)(const XivePresenter *xptr); uint32_t (*get_config)(XivePresenter *xptr); int (*broadcast)(XivePresenter *xptr, @@ -451,12 +457,14 @@ int xive_presenter_tctx_match(XivePresenter *xptr, XiveTCTX *tctx, uint8_t format, uint8_t nvt_blk, uint32_t nvt_idx, bool cam_ignore, uint32_t logic_serv); -bool xive_presenter_notify(XiveFabric *xfb, uint8_t format, - uint8_t nvt_blk, uint32_t nvt_idx, - bool crowd, bool cam_ignore, uint8_t priority, - uint32_t logic_serv, bool *precluded); +bool xive_presenter_match(XiveFabric *xfb, uint8_t format, + uint8_t nvt_blk, uint32_t nvt_idx, + bool crowd, bool cam_ignore, uint8_t priority, + uint32_t logic_serv, XiveTCTXMatch *match); uint32_t xive_get_vpgroup_size(uint32_t nvp_index); +uint8_t xive_get_group_level(bool crowd, bool ignore, + uint32_t nvp_blk, uint32_t nvp_index); /* * XIVE Fabric (Interface between Interrupt Controller and Machine) @@ -471,10 +479,10 @@ DECLARE_CLASS_CHECKERS(XiveFabricClass, XIVE_FABRIC, struct XiveFabricClass { InterfaceClass parent; - int (*match_nvt)(XiveFabric *xfb, uint8_t format, - uint8_t nvt_blk, uint32_t nvt_idx, - bool crowd, bool cam_ignore, uint8_t priority, - uint32_t logic_serv, XiveTCTXMatch *match); + bool (*match_nvt)(XiveFabric *xfb, uint8_t format, + uint8_t nvt_blk, uint32_t nvt_idx, + bool crowd, bool cam_ignore, uint8_t priority, + uint32_t logic_serv, XiveTCTXMatch *match); int (*broadcast)(XiveFabric *xfb, uint8_t nvt_blk, uint32_t nvt_idx, bool crowd, bool cam_ignore, uint8_t priority); }; @@ -532,7 +540,7 @@ static inline uint8_t xive_ipb_to_pipr(uint8_t ibp) } /* - * XIVE Thread Interrupt Management Aera (TIMA) + * XIVE Thread Interrupt Management Area (TIMA) * * This region gives access to the registers of the thread interrupt * management context. It is four page wide, each page providing a @@ -544,6 +552,30 @@ static inline uint8_t xive_ipb_to_pipr(uint8_t ibp) #define XIVE_TM_OS_PAGE 0x2 #define XIVE_TM_USER_PAGE 0x3 +/* + * The TCTX (TIMA) has 4 rings (phys, pool, os, user), but only signals + * (raises an interrupt on) the CPU from 3 of them. Phys and pool both + * cause a hypervisor privileged interrupt so interrupts presented on + * those rings signal using the phys ring. This helper returns the signal + * regs from the given ring. + */ +static inline uint8_t *xive_tctx_signal_regs(XiveTCTX *tctx, uint8_t ring) +{ + /* + * This is a good point to add invariants to ensure nothing has tried to + * signal using the POOL ring. + */ + g_assert(tctx->regs[TM_QW2_HV_POOL + TM_NSR] == 0); + g_assert(tctx->regs[TM_QW2_HV_POOL + TM_PIPR] == 0); + g_assert(tctx->regs[TM_QW2_HV_POOL + TM_CPPR] == 0); + + if (ring == TM_QW2_HV_POOL) { + /* POOL and PHYS rings share the signal regs (PIPR, NSR, CPPR) */ + ring = TM_QW3_HV_PHYS; + } + return &tctx->regs[ring]; +} + void xive_tctx_tm_write(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset, uint64_t value, unsigned size); uint64_t xive_tctx_tm_read(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset, @@ -553,10 +585,12 @@ void xive_tctx_pic_print_info(XiveTCTX *tctx, GString *buf); Object *xive_tctx_create(Object *cpu, XivePresenter *xptr, Error **errp); void xive_tctx_reset(XiveTCTX *tctx); void xive_tctx_destroy(XiveTCTX *tctx); -void xive_tctx_pipr_update(XiveTCTX *tctx, uint8_t ring, uint8_t priority, - uint8_t group_level); +void xive_tctx_pipr_set(XiveTCTX *tctx, uint8_t ring, uint8_t priority, + uint8_t group_level); +void xive_tctx_pipr_present(XiveTCTX *tctx, uint8_t ring, uint8_t priority, + uint8_t group_level); void xive_tctx_reset_signal(XiveTCTX *tctx, uint8_t ring); -void xive_tctx_notify(XiveTCTX *tctx, uint8_t ring, uint8_t group_level); +uint64_t xive_tctx_accept(XiveTCTX *tctx, uint8_t ring); /* * KVM XIVE device helpers diff --git a/include/hw/ppc/xive2.h b/include/hw/ppc/xive2.h index 8cdf819..f4437e2 100644 --- a/include/hw/ppc/xive2.h +++ b/include/hw/ppc/xive2.h @@ -29,9 +29,11 @@ OBJECT_DECLARE_TYPE(Xive2Router, Xive2RouterClass, XIVE2_ROUTER); * Configuration flags */ -#define XIVE2_GEN1_TIMA_OS 0x00000001 -#define XIVE2_VP_SAVE_RESTORE 0x00000002 -#define XIVE2_THREADID_8BITS 0x00000004 +#define XIVE2_GEN1_TIMA_OS 0x00000001 +#define XIVE2_VP_SAVE_RESTORE 0x00000002 +#define XIVE2_THREADID_8BITS 0x00000004 +#define XIVE2_EN_VP_GRP_PRIORITY 0x00000008 +#define XIVE2_VP_INT_PRIO 0x00000030 typedef struct Xive2RouterClass { SysBusDeviceClass parent; @@ -80,6 +82,7 @@ int xive2_router_write_nvgc(Xive2Router *xrtr, bool crowd, uint32_t xive2_router_get_config(Xive2Router *xrtr); void xive2_router_notify(XiveNotifier *xn, uint32_t lisn, bool pq_checked); +void xive2_notify(Xive2Router *xrtr, uint32_t lisn, bool pq_checked); /* * XIVE2 Presenter (POWER10) @@ -127,6 +130,8 @@ void xive2_tm_set_hv_cppr(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset, uint64_t value, unsigned size); void xive2_tm_set_os_cppr(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset, uint64_t value, unsigned size); +void xive2_tm_set_os_pending(XivePresenter *xptr, XiveTCTX *tctx, + hwaddr offset, uint64_t value, unsigned size); void xive2_tm_push_os_ctx(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset, uint64_t value, unsigned size); uint64_t xive2_tm_pull_os_ctx(XivePresenter *xptr, XiveTCTX *tctx, @@ -137,7 +142,16 @@ bool xive2_tm_irq_precluded(XiveTCTX *tctx, int ring, uint8_t priority); void xive2_tm_set_lsmfb(XiveTCTX *tctx, int ring, uint8_t priority); void xive2_tm_set_hv_target(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset, uint64_t value, unsigned size); +void xive2_tm_push_pool_ctx(XivePresenter *xptr, XiveTCTX *tctx, + hwaddr offset, uint64_t value, unsigned size); +uint64_t xive2_tm_pull_pool_ctx(XivePresenter *xptr, XiveTCTX *tctx, + hwaddr offset, unsigned size); +void xive2_tm_push_phys_ctx(XivePresenter *xptr, XiveTCTX *tctx, + hwaddr offset, uint64_t value, unsigned size); +uint64_t xive2_tm_pull_phys_ctx(XivePresenter *xptr, XiveTCTX *tctx, + hwaddr offset, unsigned size); void xive2_tm_pull_phys_ctx_ol(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset, uint64_t value, unsigned size); - +void xive2_tm_ack_os_el(XivePresenter *xptr, XiveTCTX *tctx, + hwaddr offset, uint64_t value, unsigned size); #endif /* PPC_XIVE2_H */ diff --git a/include/hw/ppc/xive2_regs.h b/include/hw/ppc/xive2_regs.h index b11395c..2a3e60a 100644 --- a/include/hw/ppc/xive2_regs.h +++ b/include/hw/ppc/xive2_regs.h @@ -39,15 +39,18 @@ typedef struct Xive2Eas { uint64_t w; -#define EAS2_VALID PPC_BIT(0) -#define EAS2_END_BLOCK PPC_BITMASK(4, 7) /* Destination EQ block# */ -#define EAS2_END_INDEX PPC_BITMASK(8, 31) /* Destination EQ index */ -#define EAS2_MASKED PPC_BIT(32) /* Masked */ -#define EAS2_END_DATA PPC_BITMASK(33, 63) /* written to the EQ */ +#define EAS2_VALID PPC_BIT(0) +#define EAS2_QOS PPC_BIT(1, 2) /* Quality of Service(unimp) */ +#define EAS2_RESUME PPC_BIT(3) /* END Resume(unimp) */ +#define EAS2_END_BLOCK PPC_BITMASK(4, 7) /* Destination EQ block# */ +#define EAS2_END_INDEX PPC_BITMASK(8, 31) /* Destination EQ index */ +#define EAS2_MASKED PPC_BIT(32) /* Masked */ +#define EAS2_END_DATA PPC_BITMASK(33, 63) /* written to the EQ */ } Xive2Eas; #define xive2_eas_is_valid(eas) (be64_to_cpu((eas)->w) & EAS2_VALID) #define xive2_eas_is_masked(eas) (be64_to_cpu((eas)->w) & EAS2_MASKED) +#define xive2_eas_is_resume(eas) (be64_to_cpu((eas)->w) & EAS2_RESUME) void xive2_eas_pic_print_info(Xive2Eas *eas, uint32_t lisn, GString *buf); @@ -87,6 +90,7 @@ typedef struct Xive2End { #define END2_W2_EQ_ADDR_HI PPC_BITMASK32(8, 31) uint32_t w3; #define END2_W3_EQ_ADDR_LO PPC_BITMASK32(0, 24) +#define END2_W3_CL PPC_BIT32(27) #define END2_W3_QSIZE PPC_BITMASK32(28, 31) uint32_t w4; #define END2_W4_END_BLOCK PPC_BITMASK32(4, 7) @@ -154,6 +158,7 @@ typedef struct Xive2Nvp { #define NVP2_W0_L PPC_BIT32(8) #define NVP2_W0_G PPC_BIT32(9) #define NVP2_W0_T PPC_BIT32(10) +#define NVP2_W0_P PPC_BIT32(11) #define NVP2_W0_ESC_END PPC_BIT32(25) /* 'N' bit 0:ESB 1:END */ #define NVP2_W0_PGOFIRST PPC_BITMASK32(26, 31) uint32_t w1; @@ -205,9 +210,9 @@ static inline uint32_t xive2_nvp_idx(uint32_t cam_line) return cam_line & ((1 << XIVE2_NVP_SHIFT) - 1); } -static inline uint32_t xive2_nvp_blk(uint32_t cam_line) +static inline uint8_t xive2_nvp_blk(uint32_t cam_line) { - return (cam_line >> XIVE2_NVP_SHIFT) & 0xf; + return (uint8_t)((cam_line >> XIVE2_NVP_SHIFT) & 0xf); } void xive2_nvp_pic_print_info(Xive2Nvp *nvp, uint32_t nvp_idx, GString *buf); @@ -220,6 +225,9 @@ typedef struct Xive2Nvgc { #define NVGC2_W0_VALID PPC_BIT32(0) #define NVGC2_W0_PGONEXT PPC_BITMASK32(26, 31) uint32_t w1; +#define NVGC2_W1_PSIZE PPC_BITMASK32(0, 1) +#define NVGC2_W1_END_BLK PPC_BITMASK32(4, 7) +#define NVGC2_W1_END_IDX PPC_BITMASK32(8, 31) uint32_t w2; uint32_t w3; uint32_t w4; diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 530f3da..2caa0cb 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -725,7 +725,8 @@ void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n, * * Return: qemu_irq associated with GPIO or NULL if un-wired. */ -qemu_irq qdev_get_gpio_out_connector(DeviceState *dev, const char *name, int n); +qemu_irq qdev_get_gpio_out_connector(const DeviceState *dev, + const char *name, int n); /** * qdev_intercept_gpio_out: Intercept an existing GPIO connection @@ -1064,6 +1065,7 @@ bool qdev_set_parent_bus(DeviceState *dev, BusState *bus, Error **errp); extern bool qdev_hot_removed; char *qdev_get_dev_path(DeviceState *dev); +const char *qdev_get_printable_name(DeviceState *dev); void qbus_set_hotplug_handler(BusState *bus, Object *handler); void qbus_set_bus_hotplug_handler(BusState *bus); diff --git a/include/hw/qdev-properties-system.h b/include/hw/qdev-properties-system.h index b921392..45687be 100644 --- a/include/hw/qdev-properties-system.h +++ b/include/hw/qdev-properties-system.h @@ -32,12 +32,13 @@ extern const PropertyInfo qdev_prop_cpus390entitlement; extern const PropertyInfo qdev_prop_iothread_vq_mapping_list; extern const PropertyInfo qdev_prop_endian_mode; extern const PropertyInfo qdev_prop_vmapple_virtio_blk_variant; +extern const PropertyInfo qdev_prop_virtio_gpu_output_list; #define DEFINE_PROP_PCI_DEVFN(_n, _s, _f, _d) \ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_pci_devfn, int32_t) #define DEFINE_PROP_CHR(_n, _s, _f) \ - DEFINE_PROP(_n, _s, _f, qdev_prop_chr, CharBackend) + DEFINE_PROP(_n, _s, _f, qdev_prop_chr, CharFrontend) #define DEFINE_PROP_NETDEV(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_netdev, NICPeers) #define DEFINE_PROP_DRIVE(_n, _s, _f) \ @@ -86,7 +87,7 @@ extern const PropertyInfo qdev_prop_vmapple_virtio_blk_variant; .set_default = true) #define DEFINE_PROP_AUDIODEV(_n, _s, _f) \ - DEFINE_PROP(_n, _s, _f, qdev_prop_audiodev, QEMUSoundCard) + DEFINE_PROP(_n, _s, _f, qdev_prop_audiodev, AudioBackend *) #define DEFINE_PROP_UUID_NODEFAULT(_name, _state, _field) \ DEFINE_PROP(_name, _state, _field, qdev_prop_uuid, QemuUUID) @@ -110,4 +111,8 @@ extern const PropertyInfo qdev_prop_vmapple_virtio_blk_variant; qdev_prop_vmapple_virtio_blk_variant, \ VMAppleVirtioBlkVariant) +#define DEFINE_PROP_VIRTIO_GPU_OUTPUT_LIST(_name, _state, _field) \ + DEFINE_PROP(_name, _state, _field, qdev_prop_virtio_gpu_output_list, \ + VirtIOGPUOutputList *) + #endif diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h index 2c99856..60b8133 100644 --- a/include/hw/qdev-properties.h +++ b/include/hw/qdev-properties.h @@ -34,7 +34,7 @@ struct PropertyInfo { const char *description; const QEnumLookup *enum_table; bool realized_set_allowed; /* allow setting property on realized device */ - int (*print)(Object *obj, const Property *prop, char *dest, size_t len); + char *(*print)(Object *obj, const Property *prop); void (*set_default_value)(ObjectProperty *op, const Property *prop); ObjectProperty *(*create)(ObjectClass *oc, const char *name, const Property *prop); @@ -43,11 +43,22 @@ struct PropertyInfo { ObjectPropertyRelease *release; }; +/** + * struct OnOffAutoBit64 - OnOffAuto storage with 64 elements. + * @on_bits: Bitmap of elements with "on". + * @auto_bits: Bitmap of elements with "auto". + */ +typedef struct OnOffAutoBit64 { + uint64_t on_bits; + uint64_t auto_bits; +} OnOffAutoBit64; + /*** qdev-properties.c ***/ extern const PropertyInfo qdev_prop_bit; extern const PropertyInfo qdev_prop_bit64; +extern const PropertyInfo qdev_prop_on_off_auto_bit64; extern const PropertyInfo qdev_prop_bool; extern const PropertyInfo qdev_prop_uint8; extern const PropertyInfo qdev_prop_uint16; @@ -100,6 +111,13 @@ extern const PropertyInfo qdev_prop_link; .set_default = true, \ .defval.u = (bool)_defval) +#define DEFINE_PROP_ON_OFF_AUTO_BIT64(_name, _state, _field, _bit, _defval) \ + DEFINE_PROP(_name, _state, _field, qdev_prop_on_off_auto_bit64, \ + OnOffAutoBit64, \ + .bitnr = (_bit), \ + .set_default = true, \ + .defval.i = (OnOffAuto)_defval) + #define DEFINE_PROP_BOOL(_name, _state, _field, _defval) \ DEFINE_PROP(_name, _state, _field, qdev_prop_bool, bool, \ .set_default = true, \ diff --git a/include/hw/register.h b/include/hw/register.h index a913c52..7b0f4c8 100644 --- a/include/hw/register.h +++ b/include/hw/register.h @@ -75,10 +75,6 @@ struct RegisterAccessInfo { */ struct RegisterInfo { - /* <private> */ - DeviceState parent_obj; - - /* <public> */ void *data; int data_size; @@ -87,9 +83,8 @@ struct RegisterInfo { void *opaque; }; -#define TYPE_REGISTER "qemu-register" -DECLARE_INSTANCE_CHECKER(RegisterInfo, REGISTER, - TYPE_REGISTER) +#define TYPE_REGISTER_ARRAY "qemu-register-array" +OBJECT_DECLARE_SIMPLE_TYPE(RegisterInfoArray, REGISTER_ARRAY) /** * This structure is used to group all of the individual registers which are @@ -103,6 +98,8 @@ DECLARE_INSTANCE_CHECKER(RegisterInfo, REGISTER, */ struct RegisterInfoArray { + Object parent_obj; + MemoryRegion mem; int num_elements; @@ -212,18 +209,4 @@ RegisterInfoArray *register_init_block64(DeviceState *owner, bool debug_enabled, uint64_t memory_size); -/** - * This function should be called to cleanup the registers that were initialized - * when calling register_init_block32(). This function should only be called - * from the device's instance_finalize function. - * - * Any memory operations that the device performed that require cleanup (such - * as creating subregions) need to be called before calling this function. - * - * @r_array: A structure containing all of the registers, as returned by - * register_init_block32() - */ - -void register_finalize_block(RegisterInfoArray *r_array); - #endif diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h index 7d59b2e..51b0e13 100644 --- a/include/hw/riscv/boot.h +++ b/include/hw/riscv/boot.h @@ -43,18 +43,18 @@ bool riscv_is_32bit(RISCVHartArrayState *harts); char *riscv_plic_hart_config_string(int hart_count); void riscv_boot_info_init(RISCVBootInfo *info, RISCVHartArrayState *harts); -target_ulong riscv_calc_kernel_start_addr(RISCVBootInfo *info, - target_ulong firmware_end_addr); -target_ulong riscv_find_and_load_firmware(MachineState *machine, - const char *default_machine_firmware, - hwaddr *firmware_load_addr, - symbol_fn_t sym_cb); +hwaddr riscv_calc_kernel_start_addr(RISCVBootInfo *info, + hwaddr firmware_end_addr); +hwaddr riscv_find_and_load_firmware(MachineState *machine, + const char *default_machine_firmware, + hwaddr *firmware_load_addr, + symbol_fn_t sym_cb); const char *riscv_default_firmware_name(RISCVHartArrayState *harts); char *riscv_find_firmware(const char *firmware_filename, const char *default_machine_firmware); -target_ulong riscv_load_firmware(const char *firmware_filename, - hwaddr *firmware_load_addr, - symbol_fn_t sym_cb); +hwaddr riscv_load_firmware(const char *firmware_filename, + hwaddr *firmware_load_addr, + symbol_fn_t sym_cb); void riscv_load_kernel(MachineState *machine, RISCVBootInfo *info, target_ulong kernel_start_addr, diff --git a/include/hw/riscv/boot_opensbi.h b/include/hw/riscv/boot_opensbi.h index 18664a1..ab9999b 100644 --- a/include/hw/riscv/boot_opensbi.h +++ b/include/hw/riscv/boot_opensbi.h @@ -29,17 +29,17 @@ enum sbi_scratch_options { }; /** Representation dynamic info passed by previous booting stage */ -struct fw_dynamic_info { +struct fw_dynamic_info64 { /** Info magic */ - target_long magic; + int64_t magic; /** Info version */ - target_long version; + int64_t version; /** Next booting stage address */ - target_long next_addr; + int64_t next_addr; /** Next booting stage mode */ - target_long next_mode; + int64_t next_mode; /** Options for OpenSBI library */ - target_long options; + int64_t options; /** * Preferred boot HART id * @@ -55,7 +55,7 @@ struct fw_dynamic_info { * stage can set it to -1UL which will force the FW_DYNAMIC firmware * to use the relocation lottery mechanism. */ - target_long boot_hart; + int64_t boot_hart; }; /** Representation dynamic info passed by previous booting stage */ diff --git a/include/hw/riscv/iommu.h b/include/hw/riscv/iommu.h index b03339d..25f1a8b 100644 --- a/include/hw/riscv/iommu.h +++ b/include/hw/riscv/iommu.h @@ -24,20 +24,15 @@ #define TYPE_RISCV_IOMMU "riscv-iommu" OBJECT_DECLARE_SIMPLE_TYPE(RISCVIOMMUState, RISCV_IOMMU) -typedef struct RISCVIOMMUState RISCVIOMMUState; #define TYPE_RISCV_IOMMU_MEMORY_REGION "riscv-iommu-mr" typedef struct RISCVIOMMUSpace RISCVIOMMUSpace; #define TYPE_RISCV_IOMMU_PCI "riscv-iommu-pci" -OBJECT_DECLARE_TYPE(RISCVIOMMUStatePci, RISCVIOMMUPciClass, RISCV_IOMMU_PCI) -typedef struct RISCVIOMMUStatePci RISCVIOMMUStatePci; -typedef struct RISCVIOMMUPciClass RISCVIOMMUPciClass; +OBJECT_DECLARE_SIMPLE_TYPE(RISCVIOMMUStatePci, RISCV_IOMMU_PCI) #define TYPE_RISCV_IOMMU_SYS "riscv-iommu-device" -OBJECT_DECLARE_TYPE(RISCVIOMMUStateSys, RISCVIOMMUSysClass, RISCV_IOMMU_SYS) -typedef struct RISCVIOMMUStateSys RISCVIOMMUStateSys; -typedef struct RISCVIOMMUSysClass RISCVIOMMUSysClass; +OBJECT_DECLARE_SIMPLE_TYPE(RISCVIOMMUStateSys, RISCV_IOMMU_SYS) #define FDT_IRQ_TYPE_EDGE_LOW 1 diff --git a/include/hw/riscv/xiangshan_kmh.h b/include/hw/riscv/xiangshan_kmh.h new file mode 100644 index 0000000..c5dc6b1 --- /dev/null +++ b/include/hw/riscv/xiangshan_kmh.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * QEMU RISC-V Board Compatible with the Xiangshan Kunminghu + * FPGA prototype platform + * + * Copyright (c) 2025 Beijing Institute of Open Source Chip (BOSC) + * + */ + +#ifndef HW_XIANGSHAN_KMH_H +#define HW_XIANGSHAN_KMH_H + +#include "hw/boards.h" +#include "hw/riscv/riscv_hart.h" + +#define XIANGSHAN_KMH_MAX_CPUS 16 + +typedef struct XiangshanKmhSoCState { + /*< private >*/ + DeviceState parent_obj; + + /*< public >*/ + RISCVHartArrayState cpus; + DeviceState *irqchip; + MemoryRegion rom; +} XiangshanKmhSoCState; + +#define TYPE_XIANGSHAN_KMH_SOC "xiangshan.kunminghu.soc" +DECLARE_INSTANCE_CHECKER(XiangshanKmhSoCState, XIANGSHAN_KMH_SOC, + TYPE_XIANGSHAN_KMH_SOC) + +typedef struct XiangshanKmhState { + /*< private >*/ + MachineState parent_obj; + + /*< public >*/ + XiangshanKmhSoCState soc; +} XiangshanKmhState; + +#define TYPE_XIANGSHAN_KMH_MACHINE MACHINE_TYPE_NAME("xiangshan-kunminghu") +DECLARE_INSTANCE_CHECKER(XiangshanKmhState, XIANGSHAN_KMH_MACHINE, + TYPE_XIANGSHAN_KMH_MACHINE) + +enum { + XIANGSHAN_KMH_ROM, + XIANGSHAN_KMH_UART0, + XIANGSHAN_KMH_CLINT, + XIANGSHAN_KMH_APLIC_M, + XIANGSHAN_KMH_APLIC_S, + XIANGSHAN_KMH_IMSIC_M, + XIANGSHAN_KMH_IMSIC_S, + XIANGSHAN_KMH_DRAM, +}; + +enum { + XIANGSHAN_KMH_UART0_IRQ = 10, +}; + +/* Indicating Timebase-freq (1MHZ) */ +#define XIANGSHAN_KMH_CLINT_TIMEBASE_FREQ 1000000 + +#define XIANGSHAN_KMH_IMSIC_NUM_IDS 255 +#define XIANGSHAN_KMH_IMSIC_NUM_GUESTS 7 +#define XIANGSHAN_KMH_IMSIC_GUEST_BITS 3 + +#define XIANGSHAN_KMH_APLIC_NUM_SOURCES 96 + +#endif diff --git a/include/hw/s390x/ap-bridge.h b/include/hw/s390x/ap-bridge.h index 470e439..7efc529 100644 --- a/include/hw/s390x/ap-bridge.h +++ b/include/hw/s390x/ap-bridge.h @@ -16,4 +16,43 @@ void s390_init_ap(void); +typedef struct ChscSeiNt0Res { + uint16_t length; + uint16_t code; + uint8_t reserved1; + uint16_t reserved2; + uint8_t nt; +#define PENDING_EVENT_INFO_BITMASK 0x80; + uint8_t flags; + uint8_t reserved3; + uint8_t rs; + uint8_t cc; +} QEMU_PACKED ChscSeiNt0Res; + +#define NT0_RES_RESPONSE_CODE 1 +#define NT0_RES_NT_DEFAULT 0 +#define NT0_RES_RS_AP_CHANGE 5 +#define NT0_RES_CC_AP_CHANGE 3 + +#define EVENT_INFORMATION_NOT_STORED 1 +#define EVENT_INFORMATION_STORED 0 + +/** + * ap_chsc_sei_nt0_get_event - Retrieve the next pending AP config + * change event + * @res: Pointer to a ChscSeiNt0Res struct to be filled with event + * data + * + * This function checks for any pending AP config change events and, + * if present, populates the provided response structure with the + * appropriate SEI NT0 fields. + * + * Return: + * EVENT_INFORMATION_STORED - An event was available and written to @res + * EVENT_INFORMATION_NOT_STORED - No event was available + */ +int ap_chsc_sei_nt0_get_event(void *res); + +bool ap_chsc_sei_nt0_have_event(void); + #endif diff --git a/include/hw/s390x/cpu-topology.h b/include/hw/s390x/cpu-topology.h index 9283c94..d5e9aa4 100644 --- a/include/hw/s390x/cpu-topology.h +++ b/include/hw/s390x/cpu-topology.h @@ -13,7 +13,7 @@ #include "qemu/queue.h" #include "hw/boards.h" -#include "qapi/qapi-types-machine-target.h" +#include "qapi/qapi-types-machine-s390x.h" #define S390_TOPOLOGY_CPU_IFL 0x03 diff --git a/include/hw/s390x/event-facility.h b/include/hw/s390x/event-facility.h index ff874e7..eac7a51 100644 --- a/include/hw/s390x/event-facility.h +++ b/include/hw/s390x/event-facility.h @@ -25,6 +25,7 @@ #define SCLP_EVENT_MESSAGE 0x02 #define SCLP_EVENT_CONFIG_MGT_DATA 0x04 #define SCLP_EVENT_PMSGCMD 0x09 +#define SCLP_EVENT_CTRL_PGM_ID 0x0b #define SCLP_EVENT_ASCII_CONSOLE_DATA 0x1a #define SCLP_EVENT_SIGNAL_QUIESCE 0x1d @@ -35,6 +36,7 @@ #define SCLP_EVENT_MASK_MSG SCLP_EVMASK(SCLP_EVENT_MESSAGE) #define SCLP_EVENT_MASK_CONFIG_MGT_DATA SCLP_EVMASK(SCLP_EVENT_CONFIG_MGT_DATA) #define SCLP_EVENT_MASK_PMSGCMD SCLP_EVMASK(SCLP_EVENT_PMSGCMD) +#define SCLP_EVENT_MASK_CTRL_PGM_ID SCLP_EVMASK(SCLP_EVENT_CTRL_PGM_ID) #define SCLP_EVENT_MASK_MSG_ASCII SCLP_EVMASK(SCLP_EVENT_ASCII_CONSOLE_DATA) #define SCLP_EVENT_MASK_SIGNAL_QUIESCE SCLP_EVMASK(SCLP_EVENT_SIGNAL_QUIESCE) @@ -191,6 +193,21 @@ struct SCLPEventClass { bool (*can_handle_event)(uint8_t type); }; +#define TYPE_SCLP_EVENT_CPI "sclpcpi" +typedef struct SCLPEventCPIClass SCLPEventCPIClass; +typedef struct SCLPEventCPI SCLPEventCPI; +OBJECT_DECLARE_TYPE(SCLPEventCPI, SCLPEventCPIClass, + SCLP_EVENT_CPI) + +struct SCLPEventCPI { + SCLPEvent event; + uint8_t system_type[8]; + uint8_t system_name[8]; + uint64_t system_level; + uint8_t sysplex_name[8]; + uint64_t timestamp; +}; + #define TYPE_SCLP_EVENT_FACILITY "s390-sclp-event-facility" typedef struct SCLPEventFacility SCLPEventFacility; typedef struct SCLPEventFacilityClass SCLPEventFacilityClass; diff --git a/include/hw/s390x/s390-pci-kvm.h b/include/hw/s390x/s390-pci-kvm.h index 933814a..c33f283 100644 --- a/include/hw/s390x/s390-pci-kvm.h +++ b/include/hw/s390x/s390-pci-kvm.h @@ -14,12 +14,19 @@ #include "hw/s390x/s390-pci-bus.h" #include "hw/s390x/s390-pci-inst.h" +#include "system/kvm.h" #ifdef CONFIG_KVM +static inline void s390_pcihost_kvm_realize(void) +{ + kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled(); +} + bool s390_pci_kvm_interp_allowed(void); int s390_pci_kvm_aif_enable(S390PCIBusDevice *pbdev, ZpciFib *fib, bool assist); int s390_pci_kvm_aif_disable(S390PCIBusDevice *pbdev); #else +static inline void s390_pcihost_kvm_realize(void) {} static inline bool s390_pci_kvm_interp_allowed(void) { return false; diff --git a/include/hw/s390x/s390-virtio-ccw.h b/include/hw/s390x/s390-virtio-ccw.h index 321b26d..526078a 100644 --- a/include/hw/s390x/s390-virtio-ccw.h +++ b/include/hw/s390x/s390-virtio-ccw.h @@ -54,6 +54,7 @@ struct S390CcwMachineClass { /*< public >*/ int max_threads; + bool use_cpi; }; #endif diff --git a/include/hw/s390x/sclp.h b/include/hw/s390x/sclp.h index d32f618..33f01f8 100644 --- a/include/hw/s390x/sclp.h +++ b/include/hw/s390x/sclp.h @@ -197,12 +197,9 @@ OBJECT_DECLARE_TYPE(SCLPDevice, SCLPDeviceClass, struct SCLPEventFacility; struct SCLPDevice { - /* private */ DeviceState parent_obj; - struct SCLPEventFacility *event_facility; - int increment_size; - /* public */ + struct SCLPEventFacility *event_facility; }; struct SCLPDeviceClass { diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h index 533d856..3526bad 100644 --- a/include/hw/scsi/esp.h +++ b/include/hw/scsi/esp.h @@ -14,7 +14,11 @@ typedef void (*ESPDMAMemoryReadWriteFunc)(void *opaque, uint8_t *buf, int len); #define ESP_FIFO_SZ 16 #define ESP_CMDFIFO_SZ 32 -typedef struct ESPState ESPState; +enum ESPASCMode { + ESP_ASC_MODE_DIS = 0, /* Disconnected */ + ESP_ASC_MODE_INI = 1, /* Initiator */ + ESP_ASC_MODE_TGT = 2 /* Target */ +}; #define TYPE_ESP "esp" OBJECT_DECLARE_SIMPLE_TYPE(ESPState, ESP) @@ -40,6 +44,7 @@ struct ESPState { uint8_t cmdfifo_cdb_offset; uint8_t lun; uint32_t do_cmd; + uint8_t asc_mode; bool data_ready; int dma_enabled; @@ -106,6 +111,13 @@ struct SysBusESPState { #define CMD_DMA 0x80 #define CMD_CMD 0x7f +#define CMD_GRP_MASK 0x70 + +#define CMD_GRP_MISC 0x00 +#define CMD_GRP_INIT 0x01 +#define CMD_GRP_TRGT 0x02 +#define CMD_GRP_DISC 0x04 + #define CMD_NOP 0x00 #define CMD_FLUSH 0x01 #define CMD_RESET 0x02 @@ -140,6 +152,7 @@ struct SysBusESPState { #define INTR_FC 0x08 #define INTR_BS 0x10 #define INTR_DC 0x20 +#define INTR_IL 0x40 #define INTR_RST 0x80 #define SEQ_0 0x0 diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h index 90ee192..044bd04 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h @@ -10,7 +10,9 @@ #define MAX_SCSI_DEVS 255 -typedef struct SCSIBus SCSIBus; +#define TYPE_SCSI_BUS "SCSI" +OBJECT_DECLARE_SIMPLE_TYPE(SCSIBus, SCSI_BUS) + typedef struct SCSIBusInfo SCSIBusInfo; typedef struct SCSIDevice SCSIDevice; typedef struct SCSIRequest SCSIRequest; @@ -151,9 +153,6 @@ struct SCSIBusInfo { void (*drained_end)(SCSIBus *bus); }; -#define TYPE_SCSI_BUS "SCSI" -OBJECT_DECLARE_SIMPLE_TYPE(SCSIBus, SCSI_BUS) - struct SCSIBus { BusState qbus; int busnr; diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h index d6bad17..91b5c40 100644 --- a/include/hw/sd/sd.h +++ b/include/hw/sd/sd.h @@ -56,7 +56,6 @@ #define AKE_SEQ_ERROR (1 << 3) enum SDPhySpecificationVersion { - SD_PHY_SPECv1_10_VERS = 1, SD_PHY_SPECv2_00_VERS = 2, SD_PHY_SPECv3_01_VERS = 3, }; @@ -96,7 +95,17 @@ struct SDCardClass { DeviceClass parent_class; /*< public >*/ - int (*do_command)(SDState *sd, SDRequest *req, uint8_t *response); + /** + * Process a SD command request. + * @sd: card + * @req: command request + * @resp: buffer to receive the command response + * @respsz: size of @resp buffer + * + * Return: size of the response + */ + size_t (*do_command)(SDState *sd, SDRequest *req, + uint8_t *resp, size_t respsz); /** * Write a byte to a SD card. * @sd: card @@ -153,7 +162,16 @@ struct SDBusClass { void sdbus_set_voltage(SDBus *sdbus, uint16_t millivolts); uint8_t sdbus_get_dat_lines(SDBus *sdbus); bool sdbus_get_cmd_line(SDBus *sdbus); -int sdbus_do_command(SDBus *sd, SDRequest *req, uint8_t *response); +/** + * sdbus_do_command: Process a SD command request + * @sd: card + * @req: command request + * @resp: buffer to receive the command response + * @respsz: size of @resp buffer + * + * Return: size of the response + */ +size_t sdbus_do_command(SDBus *sd, SDRequest *req, uint8_t *resp, size_t respsz); /** * Write a byte to a SD bus. * @sd: bus diff --git a/include/hw/southbridge/ich9.h b/include/hw/southbridge/ich9.h index 1e231e8..2c35dd0 100644 --- a/include/hw/southbridge/ich9.h +++ b/include/hw/southbridge/ich9.h @@ -95,7 +95,7 @@ struct ICH9LPCState { #define ICH9_CC_OIC 0x31FF #define ICH9_CC_OIC_AEN 0x1 #define ICH9_CC_GCS 0x3410 -#define ICH9_CC_GCS_DEFAULT 0x00000020 +#define ICH9_CC_GCS_DEFAULT 0x00000000 #define ICH9_CC_GCS_NO_REBOOT (1 << 5) /* D28:F[0-5] */ diff --git a/include/hw/ssi/ssi.h b/include/hw/ssi/ssi.h index 3cdcbd5..2ad8033 100644 --- a/include/hw/ssi/ssi.h +++ b/include/hw/ssi/ssi.h @@ -38,6 +38,7 @@ struct SSIPeripheralClass { /* if you have standard or no CS behaviour, just override transfer. * This is called when the device cs is active (true by default). + * See ssi_transfer(). */ uint32_t (*transfer)(SSIPeripheral *dev, uint32_t val); /* called when the CS line changes. Optional, devices only need to implement @@ -52,6 +53,7 @@ struct SSIPeripheralClass { * of the CS behaviour at the device level. transfer, set_cs, and * cs_polarity are unused if this is overwritten. Transfer_raw will * always be called for the device for every txrx access to the parent bus + * See ssi_transfer(). */ uint32_t (*transfer_raw)(SSIPeripheral *dev, uint32_t val); }; @@ -110,6 +112,18 @@ bool ssi_realize_and_unref(DeviceState *dev, SSIBus *bus, Error **errp); /* Master interface. */ SSIBus *ssi_create_bus(DeviceState *parent, const char *name); +/** + * Transfer a word on a SSI bus + * @bus: SSI bus + * @val: word to transmit + * + * At the same time, read a word and write the @val one on the SSI bus. + * + * SSI words might vary between 8 and 32 bits. The same number of bits + * written is received. + * + * Return: word value received + */ uint32_t ssi_transfer(SSIBus *bus, uint32_t val); DeviceState *ssi_get_cs(SSIBus *bus, uint8_t cs_index); diff --git a/include/hw/sysbus.h b/include/hw/sysbus.h index 7dc88aa..69eb62e 100644 --- a/include/hw/sysbus.h +++ b/include/hw/sysbus.h @@ -70,18 +70,19 @@ struct SysBusDevice { typedef void FindSysbusDeviceFunc(SysBusDevice *sbdev, void *opaque); void sysbus_init_mmio(SysBusDevice *dev, MemoryRegion *memory); -MemoryRegion *sysbus_mmio_get_region(SysBusDevice *dev, int n); +MemoryRegion *sysbus_mmio_get_region(const SysBusDevice *dev, int n); void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p); void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target); void sysbus_init_ioports(SysBusDevice *dev, uint32_t ioport, uint32_t size); -bool sysbus_has_irq(SysBusDevice *dev, int n); -bool sysbus_has_mmio(SysBusDevice *dev, unsigned int n); +bool sysbus_has_irq(const SysBusDevice *dev, int n); +bool sysbus_has_mmio(const SysBusDevice *dev, unsigned int n); void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq); -bool sysbus_is_irq_connected(SysBusDevice *dev, int n); -qemu_irq sysbus_get_connected_irq(SysBusDevice *dev, int n); +bool sysbus_is_irq_connected(const SysBusDevice *dev, int n); +qemu_irq sysbus_get_connected_irq(const SysBusDevice *dev, int n); void sysbus_mmio_map(SysBusDevice *dev, int n, hwaddr addr); +int sysbus_mmio_map_name(SysBusDevice *dev, const char*name, hwaddr addr); void sysbus_mmio_map_overlap(SysBusDevice *dev, int n, hwaddr addr, int priority); diff --git a/include/hw/timer/aspeed_timer.h b/include/hw/timer/aspeed_timer.h index 767cae4..a850625 100644 --- a/include/hw/timer/aspeed_timer.h +++ b/include/hw/timer/aspeed_timer.h @@ -16,8 +16,7 @@ * 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, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * with this program; if not, see <https://www.gnu.org/licenses/>. */ #ifndef ASPEED_TIMER_H #define ASPEED_TIMER_H diff --git a/include/hw/timer/i8254.h b/include/hw/timer/i8254.h index 8402caa..f7148d9 100644 --- a/include/hw/timer/i8254.h +++ b/include/hw/timer/i8254.h @@ -75,7 +75,7 @@ static inline ISADevice *kvm_pit_init(ISABus *bus, int base) return d; } -void pit_set_gate(ISADevice *dev, int channel, int val); -void pit_get_channel_info(ISADevice *dev, int channel, PITChannelInfo *info); +void pit_set_gate(PITCommonState *pit, int channel, int val); +void pit_get_channel_info(PITCommonState *pit, int channel, PITChannelInfo *info); #endif /* HW_I8254_H */ diff --git a/include/hw/uefi/var-service.h b/include/hw/uefi/var-service.h index f7ceac4..91fb4a2 100644 --- a/include/hw/uefi/var-service.h +++ b/include/hw/uefi/var-service.h @@ -9,6 +9,7 @@ #include "qemu/uuid.h" #include "qemu/queue.h" +#include "system/memory.h" #include "hw/uefi/var-service-edk2.h" #define MAX_BUFFER_SIZE (64 * 1024) diff --git a/include/hw/vfio/vfio-amd-xgbe.h b/include/hw/vfio/vfio-amd-xgbe.h deleted file mode 100644 index a894546..0000000 --- a/include/hw/vfio/vfio-amd-xgbe.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * VFIO AMD XGBE device - * - * Copyright Linaro Limited, 2015 - * - * Authors: - * Eric Auger <eric.auger@linaro.org> - * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - * - */ - -#ifndef HW_VFIO_VFIO_AMD_XGBE_H -#define HW_VFIO_VFIO_AMD_XGBE_H - -#include "hw/vfio/vfio-platform.h" -#include "qom/object.h" - -#define TYPE_VFIO_AMD_XGBE "vfio-amd-xgbe" - -/** - * This device exposes: - * - 5 MMIO regions: MAC, PCS, SerDes Rx/Tx regs, - SerDes Integration Registers 1/2 & 2/2 - * - 2 level sensitive IRQs and optional DMA channel IRQs - */ -struct VFIOAmdXgbeDevice { - VFIOPlatformDevice vdev; -}; - -typedef struct VFIOAmdXgbeDevice VFIOAmdXgbeDevice; - -struct VFIOAmdXgbeDeviceClass { - /*< private >*/ - VFIOPlatformDeviceClass parent_class; - /*< public >*/ - DeviceRealize parent_realize; -}; - -typedef struct VFIOAmdXgbeDeviceClass VFIOAmdXgbeDeviceClass; - -DECLARE_OBJ_CHECKERS(VFIOAmdXgbeDevice, VFIOAmdXgbeDeviceClass, - VFIO_AMD_XGBE_DEVICE, TYPE_VFIO_AMD_XGBE) - -#endif diff --git a/include/hw/vfio/vfio-calxeda-xgmac.h b/include/hw/vfio/vfio-calxeda-xgmac.h deleted file mode 100644 index 8482f15..0000000 --- a/include/hw/vfio/vfio-calxeda-xgmac.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * VFIO calxeda xgmac device - * - * Copyright Linaro Limited, 2014 - * - * Authors: - * Eric Auger <eric.auger@linaro.org> - * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - * - */ - -#ifndef HW_VFIO_VFIO_CALXEDA_XGMAC_H -#define HW_VFIO_VFIO_CALXEDA_XGMAC_H - -#include "hw/vfio/vfio-platform.h" -#include "qom/object.h" - -#define TYPE_VFIO_CALXEDA_XGMAC "vfio-calxeda-xgmac" - -/** - * This device exposes: - * - a single MMIO region corresponding to its register space - * - 3 IRQS (main and 2 power related IRQs) - */ -struct VFIOCalxedaXgmacDevice { - VFIOPlatformDevice vdev; -}; -typedef struct VFIOCalxedaXgmacDevice VFIOCalxedaXgmacDevice; - -struct VFIOCalxedaXgmacDeviceClass { - /*< private >*/ - VFIOPlatformDeviceClass parent_class; - /*< public >*/ - DeviceRealize parent_realize; -}; -typedef struct VFIOCalxedaXgmacDeviceClass VFIOCalxedaXgmacDeviceClass; - -DECLARE_OBJ_CHECKERS(VFIOCalxedaXgmacDevice, VFIOCalxedaXgmacDeviceClass, - VFIO_CALXEDA_XGMAC_DEVICE, TYPE_VFIO_CALXEDA_XGMAC) - -#endif diff --git a/include/hw/vfio/vfio-container-base.h b/include/hw/vfio/vfio-container-base.h deleted file mode 100644 index 3d392b0..0000000 --- a/include/hw/vfio/vfio-container-base.h +++ /dev/null @@ -1,186 +0,0 @@ -/* - * VFIO BASE CONTAINER - * - * Copyright (C) 2023 Intel Corporation. - * Copyright Red Hat, Inc. 2023 - * - * Authors: Yi Liu <yi.l.liu@intel.com> - * Eric Auger <eric.auger@redhat.com> - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ - -#ifndef HW_VFIO_VFIO_CONTAINER_BASE_H -#define HW_VFIO_VFIO_CONTAINER_BASE_H - -#include "system/memory.h" - -typedef struct VFIODevice VFIODevice; -typedef struct VFIOIOMMUClass VFIOIOMMUClass; - -typedef struct { - unsigned long *bitmap; - hwaddr size; - hwaddr pages; -} VFIOBitmap; - -typedef struct VFIOAddressSpace { - AddressSpace *as; - QLIST_HEAD(, VFIOContainerBase) containers; - QLIST_ENTRY(VFIOAddressSpace) list; -} VFIOAddressSpace; - -/* - * This is the base object for vfio container backends - */ -typedef struct VFIOContainerBase { - Object parent; - VFIOAddressSpace *space; - MemoryListener listener; - Error *error; - bool initialized; - uint64_t dirty_pgsizes; - uint64_t max_dirty_bitmap_size; - unsigned long pgsizes; - unsigned int dma_max_mappings; - bool dirty_pages_supported; - bool dirty_pages_started; /* Protected by BQL */ - QLIST_HEAD(, VFIOGuestIOMMU) giommu_list; - QLIST_HEAD(, VFIORamDiscardListener) vrdl_list; - QLIST_ENTRY(VFIOContainerBase) next; - QLIST_HEAD(, VFIODevice) device_list; - GList *iova_ranges; - NotifierWithReturn cpr_reboot_notifier; -} VFIOContainerBase; - -typedef struct VFIOGuestIOMMU { - VFIOContainerBase *bcontainer; - IOMMUMemoryRegion *iommu_mr; - hwaddr iommu_offset; - IOMMUNotifier n; - QLIST_ENTRY(VFIOGuestIOMMU) giommu_next; -} VFIOGuestIOMMU; - -typedef struct VFIORamDiscardListener { - VFIOContainerBase *bcontainer; - MemoryRegion *mr; - hwaddr offset_within_address_space; - hwaddr size; - uint64_t granularity; - RamDiscardListener listener; - QLIST_ENTRY(VFIORamDiscardListener) next; -} VFIORamDiscardListener; - -VFIOAddressSpace *vfio_address_space_get(AddressSpace *as); -void vfio_address_space_put(VFIOAddressSpace *space); -void vfio_address_space_insert(VFIOAddressSpace *space, - VFIOContainerBase *bcontainer); - -int vfio_container_dma_map(VFIOContainerBase *bcontainer, - hwaddr iova, ram_addr_t size, - void *vaddr, bool readonly); -int vfio_container_dma_unmap(VFIOContainerBase *bcontainer, - hwaddr iova, ram_addr_t size, - IOMMUTLBEntry *iotlb, bool unmap_all); -bool vfio_container_add_section_window(VFIOContainerBase *bcontainer, - MemoryRegionSection *section, - Error **errp); -void vfio_container_del_section_window(VFIOContainerBase *bcontainer, - MemoryRegionSection *section); -int vfio_container_set_dirty_page_tracking(VFIOContainerBase *bcontainer, - bool start, Error **errp); -bool vfio_container_dirty_tracking_is_started( - const VFIOContainerBase *bcontainer); -bool vfio_container_devices_dirty_tracking_is_supported( - const VFIOContainerBase *bcontainer); -int vfio_container_query_dirty_bitmap(const VFIOContainerBase *bcontainer, - uint64_t iova, uint64_t size, ram_addr_t ram_addr, Error **errp); - -GList *vfio_container_get_iova_ranges(const VFIOContainerBase *bcontainer); - -static inline uint64_t -vfio_container_get_page_size_mask(const VFIOContainerBase *bcontainer) -{ - assert(bcontainer); - return bcontainer->pgsizes; -} - -#define TYPE_VFIO_IOMMU "vfio-iommu" -#define TYPE_VFIO_IOMMU_LEGACY TYPE_VFIO_IOMMU "-legacy" -#define TYPE_VFIO_IOMMU_SPAPR TYPE_VFIO_IOMMU "-spapr" -#define TYPE_VFIO_IOMMU_IOMMUFD TYPE_VFIO_IOMMU "-iommufd" - -OBJECT_DECLARE_TYPE(VFIOContainerBase, VFIOIOMMUClass, VFIO_IOMMU) - -struct VFIOIOMMUClass { - ObjectClass parent_class; - - /* basic feature */ - bool (*setup)(VFIOContainerBase *bcontainer, Error **errp); - void (*listener_begin)(VFIOContainerBase *bcontainer); - void (*listener_commit)(VFIOContainerBase *bcontainer); - int (*dma_map)(const VFIOContainerBase *bcontainer, - hwaddr iova, ram_addr_t size, - void *vaddr, bool readonly); - /** - * @dma_unmap - * - * Unmap an address range from the container. - * - * @bcontainer: #VFIOContainerBase to use for unmap - * @iova: start address to unmap - * @size: size of the range to unmap - * @iotlb: The IOMMU TLB mapping entry (or NULL) - * @unmap_all: if set, unmap the entire address space - */ - int (*dma_unmap)(const VFIOContainerBase *bcontainer, - hwaddr iova, ram_addr_t size, - IOMMUTLBEntry *iotlb, bool unmap_all); - bool (*attach_device)(const char *name, VFIODevice *vbasedev, - AddressSpace *as, Error **errp); - void (*detach_device)(VFIODevice *vbasedev); - - /* migration feature */ - - /** - * @set_dirty_page_tracking - * - * Start or stop dirty pages tracking on VFIO container - * - * @bcontainer: #VFIOContainerBase on which to de/activate dirty - * page tracking - * @start: indicates whether to start or stop dirty pages tracking - * @errp: pointer to Error*, to store an error if it happens. - * - * Returns zero to indicate success and negative for error - */ - int (*set_dirty_page_tracking)(const VFIOContainerBase *bcontainer, - bool start, Error **errp); - /** - * @query_dirty_bitmap - * - * Get bitmap of dirty pages from container - * - * @bcontainer: #VFIOContainerBase from which to get dirty pages - * @vbmap: #VFIOBitmap internal bitmap structure - * @iova: iova base address - * @size: size of iova range - * @errp: pointer to Error*, to store an error if it happens. - * - * Returns zero to indicate success and negative for error - */ - int (*query_dirty_bitmap)(const VFIOContainerBase *bcontainer, - VFIOBitmap *vbmap, hwaddr iova, hwaddr size, Error **errp); - /* PCI specific */ - int (*pci_hot_reset)(VFIODevice *vbasedev, bool single); - - /* SPAPR specific */ - bool (*add_window)(VFIOContainerBase *bcontainer, - MemoryRegionSection *section, - Error **errp); - void (*del_window)(VFIOContainerBase *bcontainer, - MemoryRegionSection *section); - void (*release)(VFIOContainerBase *bcontainer); -}; - -#endif /* HW_VFIO_VFIO_CONTAINER_BASE_H */ diff --git a/include/hw/vfio/vfio-container-legacy.h b/include/hw/vfio/vfio-container-legacy.h new file mode 100644 index 0000000..fe82212 --- /dev/null +++ b/include/hw/vfio/vfio-container-legacy.h @@ -0,0 +1,39 @@ +/* + * VFIO container + * + * Copyright Red Hat, Inc. 2025 + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_VFIO_CONTAINER_LEGACY_H +#define HW_VFIO_CONTAINER_LEGACY_H + +#include "hw/vfio/vfio-container.h" +#include "hw/vfio/vfio-cpr.h" + +OBJECT_DECLARE_SIMPLE_TYPE(VFIOLegacyContainer, VFIO_IOMMU_LEGACY); + +typedef struct VFIODevice VFIODevice; + +typedef struct VFIOGroup { + int fd; + int groupid; + VFIOLegacyContainer *container; + QLIST_HEAD(, VFIODevice) device_list; + QLIST_ENTRY(VFIOGroup) next; + QLIST_ENTRY(VFIOGroup) container_next; + bool ram_block_discard_allowed; +} VFIOGroup; + +struct VFIOLegacyContainer { + VFIOContainer parent_obj; + + int fd; /* /dev/vfio/vfio, empowered by the attached groups */ + unsigned iommu_type; + bool unmap_all_supported; + QLIST_HEAD(, VFIOGroup) group_list; + VFIOContainerCPR cpr; +}; + +#endif /* HW_VFIO_CONTAINER_LEGACY_H */ diff --git a/include/hw/vfio/vfio-container.h b/include/hw/vfio/vfio-container.h index afc498d..c4b58d6 100644 --- a/include/hw/vfio/vfio-container.h +++ b/include/hw/vfio/vfio-container.h @@ -1,36 +1,280 @@ /* - * VFIO container + * VFIO BASE CONTAINER * - * Copyright Red Hat, Inc. 2025 + * Copyright (C) 2023 Intel Corporation. + * Copyright Red Hat, Inc. 2023 + * + * Authors: Yi Liu <yi.l.liu@intel.com> + * Eric Auger <eric.auger@redhat.com> * * SPDX-License-Identifier: GPL-2.0-or-later */ -#ifndef HW_VFIO_CONTAINER_H -#define HW_VFIO_CONTAINER_H +#ifndef HW_VFIO_VFIO_CONTAINER_H +#define HW_VFIO_VFIO_CONTAINER_H -#include "hw/vfio/vfio-container-base.h" +#include "system/memory.h" -typedef struct VFIOContainer VFIOContainer; typedef struct VFIODevice VFIODevice; +typedef struct VFIOIOMMUClass VFIOIOMMUClass; + +typedef struct { + unsigned long *bitmap; + hwaddr size; + hwaddr pages; +} VFIOBitmap; -typedef struct VFIOGroup { - int fd; - int groupid; - VFIOContainer *container; +typedef struct VFIOAddressSpace { + AddressSpace *as; + QLIST_HEAD(, VFIOContainer) containers; + QLIST_ENTRY(VFIOAddressSpace) list; +} VFIOAddressSpace; + +/* + * This is the base object for vfio container backends + */ +struct VFIOContainer { + Object parent_obj; + + VFIOAddressSpace *space; + MemoryListener listener; + Error *error; + bool initialized; + uint64_t dirty_pgsizes; + uint64_t max_dirty_bitmap_size; + unsigned long pgsizes; + unsigned int dma_max_mappings; + bool dirty_pages_supported; + bool dirty_pages_started; /* Protected by BQL */ + QLIST_HEAD(, VFIOGuestIOMMU) giommu_list; + QLIST_HEAD(, VFIORamDiscardListener) vrdl_list; + QLIST_ENTRY(VFIOContainer) next; QLIST_HEAD(, VFIODevice) device_list; - QLIST_ENTRY(VFIOGroup) next; - QLIST_ENTRY(VFIOGroup) container_next; - bool ram_block_discard_allowed; -} VFIOGroup; + GList *iova_ranges; + NotifierWithReturn cpr_reboot_notifier; +}; + +#define TYPE_VFIO_IOMMU "vfio-iommu" +OBJECT_DECLARE_TYPE(VFIOContainer, VFIOIOMMUClass, VFIO_IOMMU) + +typedef struct VFIOGuestIOMMU { + VFIOContainer *bcontainer; + IOMMUMemoryRegion *iommu_mr; + hwaddr iommu_offset; + IOMMUNotifier n; + QLIST_ENTRY(VFIOGuestIOMMU) giommu_next; +} VFIOGuestIOMMU; + +typedef struct VFIORamDiscardListener { + VFIOContainer *bcontainer; + MemoryRegion *mr; + hwaddr offset_within_address_space; + hwaddr size; + uint64_t granularity; + RamDiscardListener listener; + QLIST_ENTRY(VFIORamDiscardListener) next; +} VFIORamDiscardListener; + +VFIOAddressSpace *vfio_address_space_get(AddressSpace *as); +void vfio_address_space_put(VFIOAddressSpace *space); +void vfio_address_space_insert(VFIOAddressSpace *space, + VFIOContainer *bcontainer); + +int vfio_container_dma_map(VFIOContainer *bcontainer, + hwaddr iova, uint64_t size, + void *vaddr, bool readonly, MemoryRegion *mr); +int vfio_container_dma_unmap(VFIOContainer *bcontainer, + hwaddr iova, uint64_t size, + IOMMUTLBEntry *iotlb, bool unmap_all); +bool vfio_container_add_section_window(VFIOContainer *bcontainer, + MemoryRegionSection *section, + Error **errp); +void vfio_container_del_section_window(VFIOContainer *bcontainer, + MemoryRegionSection *section); +int vfio_container_set_dirty_page_tracking(VFIOContainer *bcontainer, + bool start, Error **errp); +bool vfio_container_dirty_tracking_is_started( + const VFIOContainer *bcontainer); +bool vfio_container_devices_dirty_tracking_is_supported( + const VFIOContainer *bcontainer); +int vfio_container_query_dirty_bitmap(const VFIOContainer *bcontainer, + uint64_t iova, uint64_t size, + hwaddr translated_addr, Error **errp); + +GList *vfio_container_get_iova_ranges(const VFIOContainer *bcontainer); + +static inline uint64_t +vfio_container_get_page_size_mask(const VFIOContainer *bcontainer) +{ + assert(bcontainer); + return bcontainer->pgsizes; +} + +#define TYPE_VFIO_IOMMU_LEGACY TYPE_VFIO_IOMMU "-legacy" +#define TYPE_VFIO_IOMMU_SPAPR TYPE_VFIO_IOMMU "-spapr" +#define TYPE_VFIO_IOMMU_IOMMUFD TYPE_VFIO_IOMMU "-iommufd" +#define TYPE_VFIO_IOMMU_USER TYPE_VFIO_IOMMU "-user" + +struct VFIOIOMMUClass { + ObjectClass parent_class; + + /** + * @setup + * + * Perform basic setup of the container, including configuring IOMMU + * capabilities, IOVA ranges, supported page sizes, etc. + * + * @bcontainer: #VFIOContainer + * @errp: pointer to Error*, to store an error if it happens. + * + * Returns true to indicate success and false for error. + */ + bool (*setup)(VFIOContainer *bcontainer, Error **errp); + + /** + * @listener_begin + * + * Called at the beginning of an address space update transaction. + * See #MemoryListener. + * + * @bcontainer: #VFIOContainer + */ + void (*listener_begin)(VFIOContainer *bcontainer); + + /** + * @listener_commit + * + * Called at the end of an address space update transaction, + * See #MemoryListener. + * + * @bcontainer: #VFIOContainer + */ + void (*listener_commit)(VFIOContainer *bcontainer); + + /** + * @dma_map + * + * Map an address range into the container. Note that the memory region is + * referenced within an RCU read lock region across this call. + * + * @bcontainer: #VFIOContainer to use + * @iova: start address to map + * @size: size of the range to map + * @vaddr: process virtual address of mapping + * @readonly: true if mapping should be readonly + * @mr: the memory region for this mapping + * + * Returns 0 to indicate success and -errno otherwise. + */ + int (*dma_map)(const VFIOContainer *bcontainer, + hwaddr iova, uint64_t size, + void *vaddr, bool readonly, MemoryRegion *mr); + /** + * @dma_map_file + * + * Map a file range for the container. + * + * @bcontainer: #VFIOContainer to use for map + * @iova: start address to map + * @size: size of the range to map + * @fd: descriptor of the file to map + * @start: starting file offset of the range to map + * @readonly: map read only if true + */ + int (*dma_map_file)(const VFIOContainer *bcontainer, + hwaddr iova, uint64_t size, + int fd, unsigned long start, bool readonly); + /** + * @dma_unmap + * + * Unmap an address range from the container. + * + * @bcontainer: #VFIOContainer to use for unmap + * @iova: start address to unmap + * @size: size of the range to unmap + * @iotlb: The IOMMU TLB mapping entry (or NULL) + * @unmap_all: if set, unmap the entire address space + * + * Returns 0 to indicate success and -errno otherwise. + */ + int (*dma_unmap)(const VFIOContainer *bcontainer, + hwaddr iova, uint64_t size, + IOMMUTLBEntry *iotlb, bool unmap_all); + + + /** + * @attach_device + * + * Associate the given device with a container and do some related + * initialization of the device context. + * + * @name: name of the device + * @vbasedev: the device + * @as: address space to use + * @errp: pointer to Error*, to store an error if it happens. + * + * Returns true to indicate success and false for error. + */ + bool (*attach_device)(const char *name, VFIODevice *vbasedev, + AddressSpace *as, Error **errp); + + /* + * @detach_device + * + * Detach the given device from its container and clean up any necessary + * state. + * + * @vbasedev: the device to disassociate + */ + void (*detach_device)(VFIODevice *vbasedev); + + /* migration feature */ + + /** + * @set_dirty_page_tracking + * + * Start or stop dirty pages tracking on VFIO container + * + * @bcontainer: #VFIOContainer on which to de/activate dirty + * page tracking + * @start: indicates whether to start or stop dirty pages tracking + * @errp: pointer to Error*, to store an error if it happens. + * + * Returns zero to indicate success and negative for error. + */ + int (*set_dirty_page_tracking)(const VFIOContainer *bcontainer, + bool start, Error **errp); + /** + * @query_dirty_bitmap + * + * Get bitmap of dirty pages from container + * + * @bcontainer: #VFIOContainer from which to get dirty pages + * @vbmap: #VFIOBitmap internal bitmap structure + * @iova: iova base address + * @size: size of iova range + * @errp: pointer to Error*, to store an error if it happens. + * + * Returns zero to indicate success and negative for error. + */ + int (*query_dirty_bitmap)(const VFIOContainer *bcontainer, + VFIOBitmap *vbmap, hwaddr iova, hwaddr size, Error **errp); + /* PCI specific */ + int (*pci_hot_reset)(VFIODevice *vbasedev, bool single); + + /* SPAPR specific */ + bool (*add_window)(VFIOContainer *bcontainer, + MemoryRegionSection *section, + Error **errp); + void (*del_window)(VFIOContainer *bcontainer, + MemoryRegionSection *section); + void (*release)(VFIOContainer *bcontainer); +}; -typedef struct VFIOContainer { - VFIOContainerBase bcontainer; - int fd; /* /dev/vfio/vfio, empowered by the attached groups */ - unsigned iommu_type; - QLIST_HEAD(, VFIOGroup) group_list; -} VFIOContainer; +VFIORamDiscardListener *vfio_find_ram_discard_listener( + VFIOContainer *bcontainer, MemoryRegionSection *section); -OBJECT_DECLARE_SIMPLE_TYPE(VFIOContainer, VFIO_IOMMU_LEGACY); +void vfio_container_region_add(VFIOContainer *bcontainer, + MemoryRegionSection *section, bool cpr_remap); -#endif /* HW_VFIO_CONTAINER_H */ +#endif /* HW_VFIO_VFIO_CONTAINER_H */ diff --git a/include/hw/vfio/vfio-cpr.h b/include/hw/vfio/vfio-cpr.h new file mode 100644 index 0000000..4606da5 --- /dev/null +++ b/include/hw/vfio/vfio-cpr.h @@ -0,0 +1,88 @@ +/* + * VFIO CPR + * + * Copyright (c) 2025 Oracle and/or its affiliates. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_VFIO_VFIO_CPR_H +#define HW_VFIO_VFIO_CPR_H + +#include "migration/misc.h" +#include "system/memory.h" + +struct VFIOLegacyContainer; +struct VFIOContainer; +struct VFIOGroup; +struct VFIODevice; +struct VFIOPCIDevice; +struct VFIOIOMMUFDContainer; +struct IOMMUFDBackend; + +typedef int (*dma_map_fn)(const struct VFIOContainer *bcontainer, + hwaddr iova, uint64_t size, void *vaddr, + bool readonly, MemoryRegion *mr); + +typedef struct VFIOContainerCPR { + Error *blocker; + bool vaddr_unmapped; + NotifierWithReturn transfer_notifier; + MemoryListener remap_listener; +} VFIOContainerCPR; + +typedef struct VFIODeviceCPR { + Error *mdev_blocker; + Error *id_blocker; + uint32_t hwpt_id; + uint32_t ioas_id; +} VFIODeviceCPR; + +typedef struct VFIOPCICPR { + NotifierWithReturn transfer_notifier; +} VFIOPCICPR; + +bool vfio_legacy_cpr_register_container(struct VFIOLegacyContainer *container, + Error **errp); +void vfio_legacy_cpr_unregister_container( + struct VFIOLegacyContainer *container); + +int vfio_cpr_reboot_notifier(NotifierWithReturn *notifier, MigrationEvent *e, + Error **errp); + +bool vfio_iommufd_cpr_register_container(struct VFIOIOMMUFDContainer *container, + Error **errp); +void vfio_iommufd_cpr_unregister_container( + struct VFIOIOMMUFDContainer *container); +bool vfio_iommufd_cpr_register_iommufd(struct IOMMUFDBackend *be, Error **errp); +void vfio_iommufd_cpr_unregister_iommufd(struct IOMMUFDBackend *be); +void vfio_iommufd_cpr_register_device(struct VFIODevice *vbasedev); +void vfio_iommufd_cpr_unregister_device(struct VFIODevice *vbasedev); +void vfio_cpr_load_device(struct VFIODevice *vbasedev); + +int vfio_cpr_group_get_device_fd(int d, const char *name); + +bool vfio_cpr_container_match(struct VFIOLegacyContainer *container, + struct VFIOGroup *group, int fd); + +void vfio_cpr_giommu_remap(struct VFIOContainer *bcontainer, + MemoryRegionSection *section); + +bool vfio_cpr_ram_discard_replay_populated( + struct VFIOContainer *bcontainer, MemoryRegionSection *section); + +void vfio_cpr_save_vector_fd(struct VFIOPCIDevice *vdev, const char *name, + int nr, int fd); +int vfio_cpr_load_vector_fd(struct VFIOPCIDevice *vdev, const char *name, + int nr); +void vfio_cpr_delete_vector_fd(struct VFIOPCIDevice *vdev, const char *name, + int nr); + +extern const VMStateDescription vfio_cpr_pci_vmstate; +extern const VMStateDescription vmstate_cpr_vfio_devices; + +void vfio_cpr_add_kvm_notifier(void); +void vfio_cpr_pci_register_device(struct VFIOPCIDevice *vdev); +void vfio_cpr_pci_unregister_device(struct VFIOPCIDevice *vdev); + +#endif /* HW_VFIO_VFIO_CPR_H */ diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-device.h index 8bcb3c1..0fe6c60 100644 --- a/include/hw/vfio/vfio-device.h +++ b/include/hw/vfio/vfio-device.h @@ -18,8 +18,8 @@ * Copyright (C) 2008, IBM, Muli Ben-Yehuda (muli@il.ibm.com) */ -#ifndef HW_VFIO_VFIO_COMMON_H -#define HW_VFIO_VFIO_COMMON_H +#ifndef HW_VFIO_VFIO_DEVICE_H +#define HW_VFIO_VFIO_DEVICE_H #include "system/memory.h" #include "qemu/queue.h" @@ -27,7 +27,8 @@ #include <linux/vfio.h> #endif #include "system/system.h" -#include "hw/vfio/vfio-container-base.h" +#include "hw/vfio/vfio-container.h" +#include "hw/vfio/vfio-cpr.h" #include "system/host_iommu_device.h" #include "system/iommufd.h" @@ -35,7 +36,7 @@ enum { VFIO_DEVICE_TYPE_PCI = 0, - VFIO_DEVICE_TYPE_PLATFORM = 1, + VFIO_DEVICE_TYPE_UNUSED = 1, VFIO_DEVICE_TYPE_CCW = 2, VFIO_DEVICE_TYPE_AP = 3, }; @@ -46,13 +47,14 @@ typedef struct VFIOMigration VFIOMigration; typedef struct IOMMUFDBackend IOMMUFDBackend; typedef struct VFIOIOASHwpt VFIOIOASHwpt; +typedef struct VFIOUserProxy VFIOUserProxy; typedef struct VFIODevice { QLIST_ENTRY(VFIODevice) next; QLIST_ENTRY(VFIODevice) container_next; QLIST_ENTRY(VFIODevice) global_next; struct VFIOGroup *group; - VFIOContainerBase *bcontainer; + VFIOContainer *bcontainer; char *sysfsdev; char *name; DeviceState *dev; @@ -65,11 +67,14 @@ typedef struct VFIODevice { bool ram_block_discard_allowed; OnOffAuto enable_migration; OnOffAuto migration_multifd_transfer; + OnOffAuto migration_load_config_after_iter; + uint64_t migration_max_queued_buffers_size; bool migration_events; + bool use_region_fds; VFIODeviceOps *ops; VFIODeviceIOOps *io_ops; unsigned int num_irqs; - unsigned int num_regions; + unsigned int num_initial_regions; unsigned int flags; VFIOMigration *migration; Error *migration_blocker; @@ -84,6 +89,9 @@ typedef struct VFIODevice { VFIOIOASHwpt *hwpt; QLIST_ENTRY(VFIODevice) hwpt_next; struct vfio_region_info **reginfo; + int *region_fds; + VFIODeviceCPR cpr; + VFIOUserProxy *proxy; } VFIODevice; struct VFIODeviceOps { @@ -164,36 +172,64 @@ struct VFIODeviceIOOps { * @device_feature * * Fill in feature info for the given device. + * + * @vdev: #VFIODevice to use + * @feat: feature information to fill in + * + * Returns 0 on success or -errno. */ - int (*device_feature)(VFIODevice *vdev, struct vfio_device_feature *); + int (*device_feature)(VFIODevice *vdev, struct vfio_device_feature *feat); /** * @get_region_info * - * Fill in @info with information on the region given by @info->index. + * Get the information for a given region on the device. + * + * @vdev: #VFIODevice to use + * @info: set @info->index to the region index to look up; the rest of the + * struct will be filled in on success + * @fd: pointer to the fd for the region; will be -1 if not found + * + * Returns 0 on success or -errno. */ int (*get_region_info)(VFIODevice *vdev, - struct vfio_region_info *info); + struct vfio_region_info *info, int *fd); /** * @get_irq_info * - * Fill in @irq with information on the IRQ given by @info->index. + * @vdev: #VFIODevice to use + * @irq: set @irq->index to the IRQ index to look up; the rest of the struct + * will be filled in on success + * + * Returns 0 on success or -errno. */ int (*get_irq_info)(VFIODevice *vdev, struct vfio_irq_info *irq); /** * @set_irqs * - * Configure IRQs as defined by @irqs. + * Configure IRQs. + * + * @vdev: #VFIODevice to use + * @irqs: IRQ configuration as defined by VFIO docs. + * + * Returns 0 on success or -errno. */ int (*set_irqs)(VFIODevice *vdev, struct vfio_irq_set *irqs); /** * @region_read * - * Read @size bytes from the region @nr at offset @off into the buffer - * @data. + * Read part of a region. + * + * @vdev: #VFIODevice to use + * @nr: region index + * @off: offset within the region + * @size: size in bytes to read + * @data: buffer to read into + * + * Returns number of bytes read on success or -errno. */ int (*region_read)(VFIODevice *vdev, uint8_t nr, off_t off, uint32_t size, void *data); @@ -201,14 +237,22 @@ struct VFIODeviceIOOps { /** * @region_write * - * Write @size bytes to the region @nr at offset @off from the buffer - * @data. + * Write part of a region. + * + * @vdev: #VFIODevice to use + * @nr: region index + * @off: offset within the region + * @size: size in bytes to write + * @data: buffer to write from + * @post: true if this is a posted write + * + * Returns number of bytes write on success or -errno. */ int (*region_write)(VFIODevice *vdev, uint8_t nr, off_t off, uint32_t size, - void *data); + void *data, bool post); }; -void vfio_device_prepare(VFIODevice *vbasedev, VFIOContainerBase *bcontainer, +void vfio_device_prepare(VFIODevice *vbasedev, VFIOContainer *bcontainer, struct vfio_device_info *info); void vfio_device_unprepare(VFIODevice *vbasedev); @@ -217,6 +261,18 @@ int vfio_device_get_region_info(VFIODevice *vbasedev, int index, struct vfio_region_info **info); int vfio_device_get_region_info_type(VFIODevice *vbasedev, uint32_t type, uint32_t subtype, struct vfio_region_info **info); + +/** + * Return the fd for mapping this region. This is either the device's fd (for + * e.g. kernel vfio), or a per-region fd (for vfio-user). + * + * @vbasedev: #VFIODevice to use + * @index: region index + * + * Returns the fd. + */ +int vfio_device_get_region_fd(VFIODevice *vbasedev, int index); + bool vfio_device_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_type); int vfio_device_get_irq_info(VFIODevice *vbasedev, int index, @@ -225,8 +281,11 @@ int vfio_device_get_irq_info(VFIODevice *vbasedev, int index, /* Returns 0 on success, or a negative errno. */ bool vfio_device_get_name(VFIODevice *vbasedev, Error **errp); +void vfio_device_free_name(VFIODevice *vbasedev); void vfio_device_set_fd(VFIODevice *vbasedev, const char *str, Error **errp); void vfio_device_init(VFIODevice *vbasedev, int type, VFIODeviceOps *ops, DeviceState *dev, bool ram_discard); int vfio_device_get_aw_bits(VFIODevice *vdev); -#endif /* HW_VFIO_VFIO_COMMON_H */ + +void vfio_kvm_device_close(void); +#endif /* HW_VFIO_VFIO_DEVICE_H */ diff --git a/include/hw/vfio/vfio-platform.h b/include/hw/vfio/vfio-platform.h deleted file mode 100644 index 256d850..0000000 --- a/include/hw/vfio/vfio-platform.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * vfio based device assignment support - platform devices - * - * Copyright Linaro Limited, 2014 - * - * Authors: - * Kim Phillips <kim.phillips@linaro.org> - * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - * - * Based on vfio based PCI device assignment support: - * Copyright Red Hat, Inc. 2012 - */ - -#ifndef HW_VFIO_VFIO_PLATFORM_H -#define HW_VFIO_VFIO_PLATFORM_H - -#include "hw/sysbus.h" -#include "hw/vfio/vfio-device.h" -#include "qemu/event_notifier.h" -#include "qemu/queue.h" -#include "qom/object.h" - -#define TYPE_VFIO_PLATFORM "vfio-platform" - -enum { - VFIO_IRQ_INACTIVE = 0, - VFIO_IRQ_PENDING = 1, - VFIO_IRQ_ACTIVE = 2, - /* VFIO_IRQ_ACTIVE_AND_PENDING cannot happen with VFIO */ -}; - -typedef struct VFIOINTp { - QLIST_ENTRY(VFIOINTp) next; /* entry for IRQ list */ - QSIMPLEQ_ENTRY(VFIOINTp) pqnext; /* entry for pending IRQ queue */ - EventNotifier *interrupt; /* eventfd triggered on interrupt */ - EventNotifier *unmask; /* eventfd for unmask on QEMU bypass */ - qemu_irq qemuirq; - struct VFIOPlatformDevice *vdev; /* back pointer to device */ - int state; /* inactive, pending, active */ - uint8_t pin; /* index */ - uint32_t flags; /* IRQ info flags */ - bool kvm_accel; /* set when QEMU bypass through KVM enabled */ -} VFIOINTp; - -/* function type for user side eventfd handler */ -typedef void (*eventfd_user_side_handler_t)(VFIOINTp *intp); - -typedef struct VFIORegion VFIORegion; - -struct VFIOPlatformDevice { - SysBusDevice sbdev; - VFIODevice vbasedev; /* not a QOM object */ - VFIORegion **regions; - QLIST_HEAD(, VFIOINTp) intp_list; /* list of IRQs */ - /* queue of pending IRQs */ - QSIMPLEQ_HEAD(, VFIOINTp) pending_intp_queue; - char *compat; /* DT compatible values, separated by NUL */ - unsigned int num_compat; /* number of compatible values */ - uint32_t mmap_timeout; /* delay to re-enable mmaps after interrupt */ - QEMUTimer *mmap_timer; /* allows fast-path resume after IRQ hit */ - QemuMutex intp_mutex; /* protect the intp_list IRQ state */ - bool irqfd_allowed; /* debug option to force irqfd on/off */ -}; -typedef struct VFIOPlatformDevice VFIOPlatformDevice; - -struct VFIOPlatformDeviceClass { - /*< private >*/ - SysBusDeviceClass parent_class; - /*< public >*/ -}; -typedef struct VFIOPlatformDeviceClass VFIOPlatformDeviceClass; - -DECLARE_OBJ_CHECKERS(VFIOPlatformDevice, VFIOPlatformDeviceClass, - VFIO_PLATFORM_DEVICE, TYPE_VFIO_PLATFORM) - -#endif /* HW_VFIO_VFIO_PLATFORM_H */ diff --git a/include/hw/vfio/vfio-region.h b/include/hw/vfio/vfio-region.h deleted file mode 100644 index cbffb26..0000000 --- a/include/hw/vfio/vfio-region.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * VFIO region - * - * Copyright Red Hat, Inc. 2025 - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ - -#ifndef HW_VFIO_REGION_H -#define HW_VFIO_REGION_H - -#include "system/memory.h" - -typedef struct VFIOMmap { - MemoryRegion mem; - void *mmap; - off_t offset; - size_t size; -} VFIOMmap; - -typedef struct VFIODevice VFIODevice; - -typedef struct VFIORegion { - struct VFIODevice *vbasedev; - off_t fd_offset; /* offset of region within device fd */ - MemoryRegion *mem; /* slow, read/write access */ - size_t size; - uint32_t flags; /* VFIO region flags (rd/wr/mmap) */ - uint32_t nr_mmaps; - VFIOMmap *mmaps; - uint8_t nr; /* cache the region number for debug */ -} VFIORegion; - - -void vfio_region_write(void *opaque, hwaddr addr, - uint64_t data, unsigned size); -uint64_t vfio_region_read(void *opaque, - hwaddr addr, unsigned size); -int vfio_region_setup(Object *obj, VFIODevice *vbasedev, VFIORegion *region, - int index, const char *name); -int vfio_region_mmap(VFIORegion *region); -void vfio_region_mmaps_set_enabled(VFIORegion *region, bool enabled); -void vfio_region_unmap(VFIORegion *region); -void vfio_region_exit(VFIORegion *region); -void vfio_region_finalize(VFIORegion *region); - -#endif /* HW_VFIO_REGION_H */ diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h index d6df209..ff94fa1 100644 --- a/include/hw/virtio/vhost-backend.h +++ b/include/hw/virtio/vhost-backend.h @@ -95,6 +95,10 @@ typedef int (*vhost_new_worker_op)(struct vhost_dev *dev, struct vhost_worker_state *worker); typedef int (*vhost_free_worker_op)(struct vhost_dev *dev, struct vhost_worker_state *worker); +typedef int (*vhost_set_features_ex_op)(struct vhost_dev *dev, + const uint64_t *features); +typedef int (*vhost_get_features_ex_op)(struct vhost_dev *dev, + uint64_t *features); typedef int (*vhost_set_features_op)(struct vhost_dev *dev, uint64_t features); typedef int (*vhost_get_features_op)(struct vhost_dev *dev, @@ -186,6 +190,8 @@ typedef struct VhostOps { vhost_free_worker_op vhost_free_worker; vhost_get_vring_worker_op vhost_get_vring_worker; vhost_attach_vring_worker_op vhost_attach_vring_worker; + vhost_set_features_ex_op vhost_set_features_ex; + vhost_get_features_ex_op vhost_get_features_ex; vhost_set_features_op vhost_set_features; vhost_get_features_op vhost_get_features; vhost_set_backend_cap_op vhost_set_backend_cap; diff --git a/include/hw/virtio/vhost-user-base.h b/include/hw/virtio/vhost-user-base.h index 51d0968..d5d2f08 100644 --- a/include/hw/virtio/vhost-user-base.h +++ b/include/hw/virtio/vhost-user-base.h @@ -20,7 +20,7 @@ struct VHostUserBase { VirtIODevice parent_obj; /* Properties */ - CharBackend chardev; + CharFrontend chardev; uint16_t virtio_id; uint32_t num_vqs; uint32_t vq_size; /* can't exceed VIRTIO_QUEUE_MAX */ @@ -44,6 +44,6 @@ struct VHostUserBaseClass { }; -#define TYPE_VHOST_USER_DEVICE "vhost-user-device" +#define TYPE_VHOST_USER_TEST_DEVICE "vhost-user-test-device" #endif /* QEMU_VHOST_USER_BASE_H */ diff --git a/include/hw/virtio/vhost-user-blk.h b/include/hw/virtio/vhost-user-blk.h index ea085ee..8158d46 100644 --- a/include/hw/virtio/vhost-user-blk.h +++ b/include/hw/virtio/vhost-user-blk.h @@ -29,7 +29,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(VHostUserBlk, VHOST_USER_BLK) struct VHostUserBlk { VirtIODevice parent_obj; - CharBackend chardev; + CharFrontend chardev; int32_t bootindex; struct virtio_blk_config blkcfg; uint16_t num_queues; @@ -50,6 +50,8 @@ struct VHostUserBlk { bool connected; /* vhost_user_blk_start/vhost_user_blk_stop */ bool started_vu; + + bool skip_get_vring_base_on_force_shutdown; }; #endif diff --git a/include/hw/virtio/vhost-user-fs.h b/include/hw/virtio/vhost-user-fs.h index 94c3aaa..5699ea0 100644 --- a/include/hw/virtio/vhost-user-fs.h +++ b/include/hw/virtio/vhost-user-fs.h @@ -24,7 +24,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(VHostUserFS, VHOST_USER_FS) typedef struct { - CharBackend chardev; + CharFrontend chardev; char *tag; uint16_t num_request_queues; uint16_t queue_size; diff --git a/include/hw/virtio/vhost-user-scmi.h b/include/hw/virtio/vhost-user-scmi.h index c90db77..30ab0d7 100644 --- a/include/hw/virtio/vhost-user-scmi.h +++ b/include/hw/virtio/vhost-user-scmi.h @@ -18,7 +18,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(VHostUserSCMI, VHOST_USER_SCMI); struct VHostUserSCMI { VirtIODevice parent; - CharBackend chardev; + CharFrontend chardev; struct vhost_virtqueue *vhost_vqs; struct vhost_dev vhost_dev; VhostUserState vhost_user; diff --git a/include/hw/virtio/vhost-user-vsock.h b/include/hw/virtio/vhost-user-vsock.h index 67aa46c..5db6938 100644 --- a/include/hw/virtio/vhost-user-vsock.h +++ b/include/hw/virtio/vhost-user-vsock.h @@ -20,7 +20,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(VHostUserVSock, VHOST_USER_VSOCK) typedef struct { - CharBackend chardev; + CharFrontend chardev; } VHostUserVSockConf; struct VHostUserVSock { diff --git a/include/hw/virtio/vhost-user.h b/include/hw/virtio/vhost-user.h index 9a3f238..55d5725 100644 --- a/include/hw/virtio/vhost-user.h +++ b/include/hw/virtio/vhost-user.h @@ -64,7 +64,7 @@ typedef struct VhostUserHostNotifier { * @memory_slots: */ typedef struct VhostUserState { - CharBackend *chr; + CharFrontend *chr; GPtrArray *notifiers; int memory_slots; bool supports_config; @@ -82,7 +82,7 @@ typedef struct VhostUserState { * * Return: true on success, false on error while setting errp. */ -bool vhost_user_init(VhostUserState *user, CharBackend *chr, Error **errp); +bool vhost_user_init(VhostUserState *user, CharFrontend *chr, Error **errp); /** * vhost_user_cleanup() - cleanup state @@ -96,7 +96,7 @@ void vhost_user_cleanup(VhostUserState *user); /** * vhost_user_async_close() - cleanup vhost-user post connection drop * @d: DeviceState for the associated device (passed to callback) - * @chardev: the CharBackend associated with the connection + * @chardev: the CharFrontend associated with the connection * @vhost: the common vhost device * @cb: the user callback function to complete the clean-up * @@ -108,7 +108,7 @@ void vhost_user_cleanup(VhostUserState *user); typedef void (*vu_async_close_fn)(DeviceState *cb); void vhost_user_async_close(DeviceState *d, - CharBackend *chardev, struct vhost_dev *vhost, + CharFrontend *chardev, struct vhost_dev *vhost, vu_async_close_fn cb); #endif diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h index 0a9575b..449bf5c 100644 --- a/include/hw/virtio/vhost-vdpa.h +++ b/include/hw/virtio/vhost-vdpa.h @@ -43,7 +43,21 @@ typedef struct vhost_vdpa_shared { struct vhost_vdpa_iova_range iova_range; QLIST_HEAD(, vdpa_iommu) iommu_list; - /* IOVA mapping used by the Shadow Virtqueue */ + /* + * IOVA mapping used by the Shadow Virtqueue + * + * It is shared among all ASID for simplicity, whether CVQ shares ASID with + * guest or not: + * - Memory listener need access to guest's memory addresses allocated in + * the IOVA tree. + * - There should be plenty of IOVA address space for both ASID not to + * worry about collisions between them. Guest's translations are still + * validated with virtio virtqueue_pop so there is no risk for the guest + * to access memory that it shouldn't. + * + * To allocate a iova tree per ASID is doable but it complicates the code + * and it is not worth it for the moment. + */ VhostIOVATree *iova_tree; /* Copy of backend features */ @@ -51,6 +65,12 @@ typedef struct vhost_vdpa_shared { bool iotlb_batch_begin_sent; + /* + * The memory listener has been registered, so DMA maps have been sent to + * the device. + */ + bool listener_registered; + /* Vdpa must send shadow addresses as IOTLB key for data queues, not GPA */ bool shadow_data; diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index 38800a7..08bbb4d 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -1,6 +1,7 @@ #ifndef VHOST_H #define VHOST_H +#include "net/vhost_net.h" #include "hw/virtio/vhost-backend.h" #include "hw/virtio/virtio.h" #include "system/memory.h" @@ -106,9 +107,9 @@ struct vhost_dev { * future use should be discouraged and the variable retired as * its easy to confuse with the VirtIO backend_features. */ - uint64_t features; - uint64_t acked_features; - uint64_t backend_features; + VIRTIO_DECLARE_FEATURES(features); + VIRTIO_DECLARE_FEATURES(acked_features); + VIRTIO_DECLARE_FEATURES(backend_features); /** * @protocol_features: is the vhost-user only feature set by @@ -143,6 +144,10 @@ struct vhost_net { struct vhost_dev dev; struct vhost_virtqueue vqs[2]; int backend; + const int *feature_bits; + int max_tx_queue_size; + SaveAcketFeatures *save_acked_features; + bool is_vhost_user; NetClientState *nc; }; @@ -238,6 +243,21 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings); int vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings); /** + * vhost_dev_force_stop() - force stop the vhost device + * @hdev: common vhost_dev structure + * @vdev: the VirtIODevice structure + * @vrings: true to have vrings disabled in this call + * + * Force stop the vhost device. After the device is stopped the notifiers + * can be disabled (@vhost_dev_disable_notifiers) and the device can + * be torn down (@vhost_dev_cleanup). Unlike @vhost_dev_stop, this doesn't + * attempt to flush in-flight backend requests by skipping GET_VRING_BASE + * entirely. + */ +int vhost_dev_force_stop(struct vhost_dev *hdev, VirtIODevice *vdev, + bool vrings); + +/** * DOC: vhost device configuration handling * * The VirtIO device configuration space is used for rarely changing @@ -301,6 +321,20 @@ void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n, bool mask); /** + * vhost_get_features_ex() - sanitize the extended features set + * @hdev: common vhost_dev structure + * @feature_bits: pointer to terminated table of feature bits + * @features: original features set, filtered out on return + * + * This is the extended variant of vhost_get_features(), supporting the + * the extended features set. Filter it with the intersection of what is + * supported by the vhost backend (hdev->features) and the supported + * feature_bits. + */ +void vhost_get_features_ex(struct vhost_dev *hdev, + const int *feature_bits, + uint64_t *features); +/** * vhost_get_features() - return a sanitised set of feature bits * @hdev: common vhost_dev structure * @feature_bits: pointer to terminated table of feature bits @@ -310,8 +344,28 @@ void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n, * is supported by the vhost backend (hdev->features), the supported * feature_bits and the requested feature set. */ -uint64_t vhost_get_features(struct vhost_dev *hdev, const int *feature_bits, - uint64_t features); +static inline uint64_t vhost_get_features(struct vhost_dev *hdev, + const int *feature_bits, + uint64_t features) +{ + uint64_t features_ex[VIRTIO_FEATURES_NU64S]; + + virtio_features_from_u64(features_ex, features); + vhost_get_features_ex(hdev, feature_bits, features_ex); + return features_ex[0]; +} + +/** + * vhost_ack_features_ex() - set vhost full set of acked_features + * @hdev: common vhost_dev structure + * @feature_bits: pointer to terminated table of feature bits + * @features: requested feature set + * + * This sets the internal hdev->acked_features to the intersection of + * the backends advertised features and the supported feature_bits. + */ +void vhost_ack_features_ex(struct vhost_dev *hdev, const int *feature_bits, + const uint64_t *features); /** * vhost_ack_features() - set vhost acked_features @@ -322,8 +376,16 @@ uint64_t vhost_get_features(struct vhost_dev *hdev, const int *feature_bits, * This sets the internal hdev->acked_features to the intersection of * the backends advertised features and the supported feature_bits. */ -void vhost_ack_features(struct vhost_dev *hdev, const int *feature_bits, - uint64_t features); +static inline void vhost_ack_features(struct vhost_dev *hdev, + const int *feature_bits, + uint64_t features) +{ + uint64_t features_ex[VIRTIO_FEATURES_NU64S]; + + virtio_features_from_u64(features_ex, features); + vhost_ack_features_ex(hdev, feature_bits, features_ex); +} + unsigned int vhost_get_max_memslots(void); unsigned int vhost_get_free_memslots(void); diff --git a/include/hw/virtio/virtio-features.h b/include/hw/virtio/virtio-features.h new file mode 100644 index 0000000..e29b7fe --- /dev/null +++ b/include/hw/virtio/virtio-features.h @@ -0,0 +1,126 @@ +/* + * Virtio features helpers + * + * Copyright 2025 Red Hat, Inc. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef QEMU_VIRTIO_FEATURES_H +#define QEMU_VIRTIO_FEATURES_H + +#include "qemu/bitops.h" + +#define VIRTIO_FEATURES_FMT "%016"PRIx64"%016"PRIx64 +#define VIRTIO_FEATURES_PR(f) (f)[1], (f)[0] + +#define VIRTIO_FEATURES_MAX 128 +#define VIRTIO_FEATURES_BIT(b) BIT_ULL((b) % 64) +#define VIRTIO_FEATURES_U64(b) ((b) / 64) +#define VIRTIO_FEATURES_NU32S (VIRTIO_FEATURES_MAX / 32) +#define VIRTIO_FEATURES_NU64S (VIRTIO_FEATURES_MAX / 64) + +#define VIRTIO_DECLARE_FEATURES(name) \ + union { \ + uint64_t name; \ + uint64_t name##_ex[VIRTIO_FEATURES_NU64S]; \ + } + +#define VIRTIO_DEFINE_PROP_FEATURE(_name, _state, _field, _bit, _defval) \ + DEFINE_PROP_BIT64(_name, _state, _field[VIRTIO_FEATURES_U64(_bit)], \ + (_bit) % 64, _defval) + +static inline void virtio_features_clear(uint64_t *features) +{ + memset(features, 0, sizeof(features[0]) * VIRTIO_FEATURES_NU64S); +} + +static inline void virtio_features_from_u64(uint64_t *features, uint64_t from) +{ + virtio_features_clear(features); + features[0] = from; +} + +static inline bool virtio_has_feature_ex(const uint64_t *features, + unsigned int fbit) +{ + assert(fbit < VIRTIO_FEATURES_MAX); + return features[VIRTIO_FEATURES_U64(fbit)] & VIRTIO_FEATURES_BIT(fbit); +} + +static inline void virtio_add_feature_ex(uint64_t *features, + unsigned int fbit) +{ + assert(fbit < VIRTIO_FEATURES_MAX); + features[VIRTIO_FEATURES_U64(fbit)] |= VIRTIO_FEATURES_BIT(fbit); +} + +static inline void virtio_clear_feature_ex(uint64_t *features, + unsigned int fbit) +{ + assert(fbit < VIRTIO_FEATURES_MAX); + features[VIRTIO_FEATURES_U64(fbit)] &= ~VIRTIO_FEATURES_BIT(fbit); +} + +static inline bool virtio_features_equal(const uint64_t *f1, + const uint64_t *f2) +{ + return !memcmp(f1, f2, sizeof(uint64_t) * VIRTIO_FEATURES_NU64S); +} + +static inline bool virtio_features_use_ex(const uint64_t *features) +{ + int i; + + for (i = 1; i < VIRTIO_FEATURES_NU64S; ++i) { + if (features[i]) { + return true; + } + } + return false; +} + +static inline bool virtio_features_empty(const uint64_t *features) +{ + return !virtio_features_use_ex(features) && !features[0]; +} + +static inline void virtio_features_copy(uint64_t *to, const uint64_t *from) +{ + memcpy(to, from, sizeof(to[0]) * VIRTIO_FEATURES_NU64S); +} + +static inline bool virtio_features_andnot(uint64_t *to, const uint64_t *f1, + const uint64_t *f2) +{ + uint64_t diff = 0; + int i; + + for (i = 0; i < VIRTIO_FEATURES_NU64S; i++) { + to[i] = f1[i] & ~f2[i]; + diff |= to[i]; + } + return diff; +} + +static inline void virtio_features_and(uint64_t *to, const uint64_t *f1, + const uint64_t *f2) +{ + int i; + + for (i = 0; i < VIRTIO_FEATURES_NU64S; i++) { + to[i] = f1[i] & f2[i]; + } +} + +static inline void virtio_features_or(uint64_t *to, const uint64_t *f1, + const uint64_t *f2) +{ + int i; + + for (i = 0; i < VIRTIO_FEATURES_NU64S; i++) { + to[i] = f1[i] | f2[i]; + } +} + +#endif diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index a42957c..58e0f91 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -20,6 +20,7 @@ #include "hw/virtio/virtio.h" #include "qemu/log.h" #include "system/vhost-user-backend.h" +#include "qapi/qapi-types-virtio.h" #include "standard-headers/linux/virtio_gpu.h" #include "standard-headers/linux/virtio_ids.h" @@ -128,6 +129,7 @@ struct virtio_gpu_base_conf { uint32_t xres; uint32_t yres; uint64_t hostmem; + VirtIOGPUOutputList *outputs; }; struct virtio_gpu_ctrl_command { @@ -167,6 +169,7 @@ struct VirtIOGPUBaseClass { #define VIRTIO_GPU_BASE_PROPERTIES(_state, _conf) \ DEFINE_PROP_UINT32("max_outputs", _state, _conf.max_outputs, 1), \ + DEFINE_PROP_VIRTIO_GPU_OUTPUT_LIST("outputs", _state, _conf.outputs), \ DEFINE_PROP_BIT("edid", _state, _conf.flags, \ VIRTIO_GPU_FLAG_EDID_ENABLED, true), \ DEFINE_PROP_UINT32("xres", _state, _conf.xres, 1280), \ @@ -254,7 +257,7 @@ struct VhostUserGPU { VhostUserBackend *vhost; int vhost_gpu_fd; /* closed by the chardev */ - CharBackend vhost_chr; + CharFrontend vhost_chr; QemuDmaBuf *dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; bool backend_blocked; }; diff --git a/include/hw/virtio/virtio-mem.h b/include/hw/virtio/virtio-mem.h index bc4f787..e0ab31b 100644 --- a/include/hw/virtio/virtio-mem.h +++ b/include/hw/virtio/virtio-mem.h @@ -134,7 +134,7 @@ struct VirtioMemSystemReset { struct VirtIOMEMClass { /* private */ - VirtIODevice parent; + VirtioDeviceClass parent_class; /* public */ void (*fill_device_info)(const VirtIOMEM *vmen, VirtioMEMDeviceInfo *vi); diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h index b9ea9e8..5b8ab7b 100644 --- a/include/hw/virtio/virtio-net.h +++ b/include/hw/virtio/virtio-net.h @@ -144,7 +144,11 @@ typedef struct VirtioNetRssData { bool enabled_software_rss; bool redirect; bool populate_hash; - uint32_t hash_types; + bool peer_hash_available; + uint32_t runtime_hash_types; + uint32_t supported_hash_types; + uint32_t peer_hash_types; + OnOffAutoBit64 specified_hash_types; uint8_t key[VIRTIO_NET_RSS_MAX_KEY_SIZE]; uint16_t indirections_len; uint16_t *indirections_table; @@ -178,7 +182,7 @@ struct VirtIONet { uint32_t has_vnet_hdr; size_t host_hdr_len; size_t guest_hdr_len; - uint64_t host_features; + VIRTIO_DECLARE_FEATURES(host_features); uint32_t rsc_timeout; uint8_t rsc4_enabled; uint8_t rsc6_enabled; diff --git a/include/hw/virtio/virtio-pci.h b/include/hw/virtio/virtio-pci.h index 1dbc385..6397529 100644 --- a/include/hw/virtio/virtio-pci.h +++ b/include/hw/virtio/virtio-pci.h @@ -32,9 +32,7 @@ DECLARE_OBJ_CHECKERS(VirtioPCIBusState, VirtioPCIBusClass, enum { VIRTIO_PCI_FLAG_BUS_MASTER_BUG_MIGRATION_BIT, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, - VIRTIO_PCI_FLAG_MIGRATE_EXTRA_BIT, VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY_BIT, - VIRTIO_PCI_FLAG_DISABLE_PCIE_BIT, VIRTIO_PCI_FLAG_PAGE_PER_VQ_BIT, VIRTIO_PCI_FLAG_ATS_BIT, VIRTIO_PCI_FLAG_INIT_DEVERR_BIT, @@ -54,12 +52,6 @@ enum { * vcpu thread using ioeventfd for some devices. */ #define VIRTIO_PCI_FLAG_USE_IOEVENTFD (1 << VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT) -/* virtio version flags */ -#define VIRTIO_PCI_FLAG_DISABLE_PCIE (1 << VIRTIO_PCI_FLAG_DISABLE_PCIE_BIT) - -/* migrate extra state */ -#define VIRTIO_PCI_FLAG_MIGRATE_EXTRA (1 << VIRTIO_PCI_FLAG_MIGRATE_EXTRA_BIT) - /* have pio notification for modern device ? */ #define VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY \ (1 << VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY_BIT) @@ -166,7 +158,7 @@ struct VirtIOPCIProxy { uint32_t nvectors; uint32_t dfselect; uint32_t gfselect; - uint32_t guest_features[2]; + uint32_t guest_features[VIRTIO_FEATURES_NU32S]; VirtIOPCIQueue vqs[VIRTIO_QUEUE_MAX]; VirtIOIRQFD *vector_irqfd; diff --git a/include/hw/virtio/virtio-pmem.h b/include/hw/virtio/virtio-pmem.h index fc4fd1f..9cce600 100644 --- a/include/hw/virtio/virtio-pmem.h +++ b/include/hw/virtio/virtio-pmem.h @@ -36,7 +36,7 @@ struct VirtIOPMEM { struct VirtIOPMEMClass { /* private */ - VirtIODevice parent; + VirtioDeviceClass parent_class; /* public */ void (*fill_device_info)(const VirtIOPMEM *pmem, VirtioPMEMDeviceInfo *vi); diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h index 31e852e..b6028bb 100644 --- a/include/hw/virtio/virtio-scsi.h +++ b/include/hw/virtio/virtio-scsi.h @@ -58,7 +58,7 @@ struct VirtIOSCSIConf { uint32_t cmd_per_lun; char *vhostfd; char *wwpn; - CharBackend chardev; + CharFrontend chardev; uint32_t boot_tpgt; IOThread *iothread; IOThreadVirtQueueMappingList *iothread_vq_mapping_list; diff --git a/include/hw/virtio/virtio-serial.h b/include/hw/virtio/virtio-serial.h index d87c62e..6064186 100644 --- a/include/hw/virtio/virtio-serial.h +++ b/include/hw/virtio/virtio-serial.h @@ -29,7 +29,8 @@ struct virtio_serial_conf { OBJECT_DECLARE_TYPE(VirtIOSerialPort, VirtIOSerialPortClass, VIRTIO_SERIAL_PORT) -typedef struct VirtIOSerial VirtIOSerial; +#define TYPE_VIRTIO_SERIAL "virtio-serial-device" +OBJECT_DECLARE_SIMPLE_TYPE(VirtIOSerial, VIRTIO_SERIAL) #define TYPE_VIRTIO_SERIAL_BUS "virtio-serial-bus" OBJECT_DECLARE_SIMPLE_TYPE(VirtIOSerialBus, VIRTIO_SERIAL_BUS) @@ -221,7 +222,5 @@ size_t virtio_serial_guest_ready(VirtIOSerialPort *port); */ void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle); -#define TYPE_VIRTIO_SERIAL "virtio-serial-device" -OBJECT_DECLARE_SIMPLE_TYPE(VirtIOSerial, VIRTIO_SERIAL) #endif diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 214d4a7..d97529c 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -16,6 +16,7 @@ #include "system/memory.h" #include "hw/qdev-core.h" +#include "hw/virtio/virtio-features.h" #include "net/net.h" #include "migration/vmstate.h" #include "qemu/event_notifier.h" @@ -121,9 +122,9 @@ struct VirtIODevice * backend (e.g. vhost) and could potentially be a subset of the * total feature set offered by QEMU. */ - uint64_t host_features; - uint64_t guest_features; - uint64_t backend_features; + VIRTIO_DECLARE_FEATURES(host_features); + VIRTIO_DECLARE_FEATURES(guest_features); + VIRTIO_DECLARE_FEATURES(backend_features); size_t config_len; void *config; @@ -177,6 +178,9 @@ struct VirtioDeviceClass { /* This is what a VirtioDevice must implement */ DeviceRealize realize; DeviceUnrealize unrealize; + void (*get_features_ex)(VirtIODevice *vdev, uint64_t *requested_features, + Error **errp); + void (*set_features_ex)(VirtIODevice *vdev, const uint64_t *val); uint64_t (*get_features)(VirtIODevice *vdev, uint64_t requested_features, Error **errp); @@ -210,8 +214,14 @@ struct VirtioDeviceClass { void (*guest_notifier_mask)(VirtIODevice *vdev, int n, bool mask); int (*start_ioeventfd)(VirtIODevice *vdev); void (*stop_ioeventfd)(VirtIODevice *vdev); - /* Called before loading queues. Useful to add queues before loading. */ - int (*pre_load_queues)(VirtIODevice *vdev); + /* + * Called before loading queues. + * If the number of queues change at runtime, use @n to know the + * number and add or remove queues accordingly. + * Note that this function is called in the middle of loading vmsd; + * no assumption should be made on states being loaded from vmsd. + */ + int (*pre_load_queues)(VirtIODevice *vdev, uint32_t n); /* Saving and loading of a device; trying to deprecate save/load * use vmsd for new devices. */ @@ -284,7 +294,6 @@ int virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes, unsigned int *out_bytes, unsigned max_in_bytes, unsigned max_out_bytes); -void virtio_notify_irqfd(VirtIODevice *vdev, VirtQueue *vq); void virtio_notify(VirtIODevice *vdev, VirtQueue *vq); int virtio_save(VirtIODevice *vdev, QEMUFile *f); @@ -366,6 +375,7 @@ void virtio_queue_reset(VirtIODevice *vdev, uint32_t queue_index); void virtio_queue_enable(VirtIODevice *vdev, uint32_t queue_index); void virtio_update_irq(VirtIODevice *vdev); int virtio_set_features(VirtIODevice *vdev, uint64_t val); +int virtio_set_features_ex(VirtIODevice *vdev, const uint64_t *val); /* Base devices. */ typedef struct VirtIOBlkConf VirtIOBlkConf; diff --git a/include/hw/xen/arch_hvm.h b/include/hw/xen/arch_hvm.h index df39c81..8bacaa4 100644 --- a/include/hw/xen/arch_hvm.h +++ b/include/hw/xen/arch_hvm.h @@ -1,5 +1,11 @@ -#if defined(TARGET_I386) || defined(TARGET_X86_64) -#include "hw/i386/xen_arch_hvm.h" -#elif defined(TARGET_ARM) || defined(TARGET_AARCH64) -#include "hw/arm/xen_arch_hvm.h" +#ifndef HW_XEN_ARCH_HVM_H +#define HW_XEN_ARCH_HVM_H + +#include <xen/hvm/ioreq.h> +#include "hw/xen/xen-hvm-common.h" + +void arch_handle_ioreq(XenIOState *state, ioreq_t *req); +void arch_xen_set_memory(XenIOState *state, + MemoryRegionSection *section, + bool add); #endif diff --git a/include/hw/xen/interface/hvm/params.h b/include/hw/xen/interface/hvm/params.h index a22b4ed..99c40b4 100644 --- a/include/hw/xen/interface/hvm/params.h +++ b/include/hw/xen/interface/hvm/params.h @@ -246,16 +246,11 @@ #define HVM_PARAM_VM_GENERATION_ID_ADDR 34 /* - * Set mode for altp2m: - * disabled: don't activate altp2m (default) + * Get mode for altp2m: + * disabled: altp2m not active (default) * mixed: allow access to all altp2m ops for both in-guest and external tools * external: allow access to external privileged tools only * limited: guest only has limited access (ie. control VMFUNC and #VE) - * - * Note that 'mixed' mode has not been evaluated for safety from a - * security perspective. Before using this mode in a - * security-critical environment, each subop should be evaluated for - * safety, with unsafe subops blacklisted in XSM. */ #define HVM_PARAM_ALTP2M 35 #define XEN_ALTP2M_disabled 0 diff --git a/include/io/channel-socket.h b/include/io/channel-socket.h index ab15577..a1ef313 100644 --- a/include/io/channel-socket.h +++ b/include/io/channel-socket.h @@ -49,6 +49,12 @@ struct QIOChannelSocket { socklen_t remoteAddrLen; ssize_t zero_copy_queued; ssize_t zero_copy_sent; + bool blocking; + /** + * This flag indicates whether any new data was successfully sent with + * zerocopy since the last qio_channel_socket_flush() call. + */ + bool new_zero_copy_sent_success; }; @@ -222,7 +228,7 @@ void qio_channel_socket_dgram_async(QIOChannelSocket *ioc, * release with a call qapi_free_SocketAddress() when no * longer required. * - * Returns: 0 on success, -1 on error + * Returns: the socket address struct, or NULL on error */ SocketAddress * qio_channel_socket_get_local_address(QIOChannelSocket *ioc, @@ -261,5 +267,18 @@ QIOChannelSocket * qio_channel_socket_accept(QIOChannelSocket *ioc, Error **errp); +/** + * qio_channel_socket_set_send_buffer: + * @ioc: the socket channel object + * @size: buffer size + * @errp: pointer to a NULL-initialized error object + * + * Set the underlying socket send buffer size. + * + * Retruns: 0 on success, or -1 on error. + */ +int qio_channel_socket_set_send_buffer(QIOChannelSocket *ioc, + size_t size, + Error **errp); #endif /* QIO_CHANNEL_SOCKET_H */ diff --git a/include/io/channel-websock.h b/include/io/channel-websock.h index e180827..6700cf8 100644 --- a/include/io/channel-websock.h +++ b/include/io/channel-websock.h @@ -61,7 +61,8 @@ struct QIOChannelWebsock { size_t payload_remain; size_t pong_remain; QIOChannelWebsockMask mask; - guint io_tag; + guint hs_io_tag; /* tracking handshake task */ + guint io_tag; /* tracking watch task */ Error *io_err; gboolean io_eof; uint8_t opcode; diff --git a/include/io/channel.h b/include/io/channel.h index 62b6571..f42be76 100644 --- a/include/io/channel.h +++ b/include/io/channel.h @@ -36,6 +36,7 @@ OBJECT_DECLARE_TYPE(QIOChannel, QIOChannelClass, #define QIO_CHANNEL_READ_FLAG_MSG_PEEK 0x1 #define QIO_CHANNEL_READ_FLAG_RELAXED_EOF 0x2 +#define QIO_CHANNEL_READ_FLAG_FD_PRESERVE_BLOCKING 0x4 typedef enum QIOChannelFeature QIOChannelFeature; @@ -46,6 +47,7 @@ enum QIOChannelFeature { QIO_CHANNEL_FEATURE_WRITE_ZERO_COPY, QIO_CHANNEL_FEATURE_READ_MSG_PEEK, QIO_CHANNEL_FEATURE_SEEKABLE, + QIO_CHANNEL_FEATURE_CONCURRENT_IO, }; @@ -116,6 +118,15 @@ struct QIOChannelClass { size_t nfds, int flags, Error **errp); + + /* + * The io_readv handler must guarantee that all + * incoming fds are set BLOCKING (unless + * QIO_CHANNEL_READ_FLAG_FD_PRESERVE_BLOCKING flag is set) and + * CLOEXEC (if available). + * @fds and @nfds are set only on success path. Still, setting + * @fds and @nfds to zero is acceptable on failure path. + */ ssize_t (*io_readv)(QIOChannel *ioc, const struct iovec *iov, size_t niov, @@ -123,6 +134,7 @@ struct QIOChannelClass { size_t *nfds, int flags, Error **errp); + int (*io_close)(QIOChannel *ioc, Error **errp); GSource * (*io_create_watch)(QIOChannel *ioc, @@ -233,6 +245,13 @@ void qio_channel_set_name(QIOChannel *ioc, * was allocated. It is the callers responsibility * to call close() on each file descriptor and to * call g_free() on the array pointer in @fds. + * @fds allocated and set (and @nfds is set too) + * _only_ on success path. Still, @fds and @nfds + * may be set to zero on failure path. + * qio_channel_readv_full() guarantees that all + * incoming fds are set BLOCKING (unless + * QIO_CHANNEL_READ_FLAG_FD_PRESERVE_BLOCKING flag + * is set) and CLOEXEC (if available). * * It is an error to pass a non-NULL @fds parameter * unless qio_channel_has_feature() returns a true @@ -418,7 +437,7 @@ ssize_t qio_channel_writev(QIOChannel *ioc, * a single memory region. */ ssize_t qio_channel_read(QIOChannel *ioc, - char *buf, + void *buf, size_t buflen, Error **errp); @@ -434,7 +453,7 @@ ssize_t qio_channel_read(QIOChannel *ioc, * single memory region. */ ssize_t qio_channel_write(QIOChannel *ioc, - const char *buf, + const void *buf, size_t buflen, Error **errp); @@ -456,7 +475,7 @@ ssize_t qio_channel_write(QIOChannel *ioc, * without data, or -1 on error */ int coroutine_mixed_fn qio_channel_read_all_eof(QIOChannel *ioc, - char *buf, + void *buf, size_t buflen, Error **errp); @@ -476,7 +495,7 @@ int coroutine_mixed_fn qio_channel_read_all_eof(QIOChannel *ioc, * Returns: 0 if all bytes were read, or -1 on error */ int coroutine_mixed_fn qio_channel_read_all(QIOChannel *ioc, - char *buf, + void *buf, size_t buflen, Error **errp); @@ -495,7 +514,7 @@ int coroutine_mixed_fn qio_channel_read_all(QIOChannel *ioc, * Returns: 0 if all bytes were written, or -1 on error */ int coroutine_mixed_fn qio_channel_write_all(QIOChannel *ioc, - const char *buf, + const void *buf, size_t buflen, Error **errp); @@ -512,9 +531,9 @@ int coroutine_mixed_fn qio_channel_write_all(QIOChannel *ioc, * return QIO_CHANNEL_ERR_BLOCK if they would otherwise * block on I/O */ -int qio_channel_set_blocking(QIOChannel *ioc, - bool enabled, - Error **errp); +bool qio_channel_set_blocking(QIOChannel *ioc, + bool enabled, + Error **errp); /** * qio_channel_set_follow_coroutine_ctx: @@ -576,7 +595,7 @@ ssize_t qio_channel_pwritev(QIOChannel *ioc, const struct iovec *iov, * flag QIO_CHANNEL_FEATURE_SEEKABLE prior to calling this method. * */ -ssize_t qio_channel_pwrite(QIOChannel *ioc, char *buf, size_t buflen, +ssize_t qio_channel_pwrite(QIOChannel *ioc, void *buf, size_t buflen, off_t offset, Error **errp); /** @@ -612,7 +631,7 @@ ssize_t qio_channel_preadv(QIOChannel *ioc, const struct iovec *iov, * flag QIO_CHANNEL_FEATURE_SEEKABLE prior to calling this method. * */ -ssize_t qio_channel_pread(QIOChannel *ioc, char *buf, size_t buflen, +ssize_t qio_channel_pread(QIOChannel *ioc, void *buf, size_t buflen, off_t offset, Error **errp); /** @@ -853,6 +872,21 @@ void qio_channel_wait(QIOChannel *ioc, GIOCondition condition); /** + * qio_channel_wait_cond: + * @ioc: the channel object + * @condition: the I/O condition to wait for + * + * Block execution from the current thread until + * the condition indicated by @condition becomes + * available. + * + * This will work with/without a coroutine context, by automatically select + * the proper API to wait. + */ +void qio_channel_wait_cond(QIOChannel *ioc, + GIOCondition condition); + +/** * qio_channel_set_aio_fd_handler: * @ioc: the channel object * @read_ctx: the AioContext to set the read handler on or NULL diff --git a/include/io/net-listener.h b/include/io/net-listener.h index ab9f291..fdc5f1c 100644 --- a/include/io/net-listener.h +++ b/include/io/net-listener.h @@ -28,6 +28,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(QIONetListener, QIO_NET_LISTENER) +typedef struct QIONetListenerSource QIONetListenerSource; typedef void (*QIONetListenerClientFunc)(QIONetListener *listener, QIOChannelSocket *sioc, @@ -47,12 +48,15 @@ struct QIONetListener { Object parent; char *name; - QIOChannelSocket **sioc; - GSource **io_source; + QIONetListenerSource **source; size_t nsioc; + /* At most one of context or aio_context will be set */ + GMainContext *context; + AioContext *aio_context; bool connected; + QemuMutex lock; /* Protects remaining fields */ QIONetListenerClientFunc io_func; gpointer io_data; GDestroyNotify io_notify; @@ -149,6 +153,27 @@ void qio_net_listener_set_client_func(QIONetListener *listener, GDestroyNotify notify); /** + * qio_net_listener_set_client_aio_func: + * @listener: the network listener object + * @func: the callback function + * @data: opaque data to pass to @func + * @context: AioContext that @func will be bound to; if NULL, this will + * will use qemu_get_aio_context(). + * + * Similar to qio_net_listener_set_client_func_full(), except that the polling + * will be done by an AioContext rather than a GMainContext. + * + * Because AioContext does not (yet) support a clean way to deregister + * a callback from one thread while another thread might be in that + * callback, this function is only safe to call from the thread + * currently associated with @context. + */ +void qio_net_listener_set_client_aio_func(QIONetListener *listener, + QIONetListenerClientFunc func, + void *data, + AioContext *context); + +/** * qio_net_listener_wait_client: * @listener: the network listener object * @@ -183,4 +208,46 @@ void qio_net_listener_disconnect(QIONetListener *listener); */ bool qio_net_listener_is_connected(QIONetListener *listener); + +/** + * qio_net_listener_nsioc: + * @listener: the network listener object + * + * Determine the number of listener channels currently owned by the + * given listener. + * + * Returns: number of channels, or 0 if not listening + */ +size_t qio_net_listener_nsioc(QIONetListener *listener); + + +/** + * qio_net_listener_sioc: + * @listener: the network listener object + * @n: index of the sioc to grab + * + * Accessor for the nth sioc owned by the listener. + * + * Returns: the requested listener, or NULL if not in bounds + */ +QIOChannelSocket *qio_net_listener_sioc(QIONetListener *listener, size_t n); + +/** + * qio_net_listener_get_local_address: + * @listener: the network listener object + * @n: index of the sioc to grab + * @errp: pointer to a NULL-initialized error object + * + * Get the string representation of the local socket + * address. A pointer to the allocated address information + * struct will be returned, which the caller is required to + * release with a call qapi_free_SocketAddress() when no + * longer required. + * + * Returns: the socket address struct, or NULL on error + */ +SocketAddress * +qio_net_listener_get_local_address(QIONetListener *listener, size_t n, + Error **errp); + #endif /* QIO_NET_LISTENER_H */ diff --git a/include/libdecnumber/dconfig.h b/include/libdecnumber/dconfig.h index 2bc0ba7f..e67ecc1 100644 --- a/include/libdecnumber/dconfig.h +++ b/include/libdecnumber/dconfig.h @@ -23,9 +23,8 @@ for more details. You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING. If not, write to the Free - Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. */ + along with GCC; see the file COPYING. If not, see + <https://www.gnu.org/licenses/>. */ #if HOST_BIG_ENDIAN diff --git a/include/libdecnumber/decContext.h b/include/libdecnumber/decContext.h index cea6e42..5bb64e1 100644 --- a/include/libdecnumber/decContext.h +++ b/include/libdecnumber/decContext.h @@ -24,9 +24,8 @@ for more details. You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING. If not, write to the Free - Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. */ + along with GCC; see the file COPYING. If not, see + <https://www.gnu.org/licenses/>. */ /* ------------------------------------------------------------------ */ /* Decimal Context module header */ diff --git a/include/libdecnumber/decDPD.h b/include/libdecnumber/decDPD.h index 26a21ec..8eb4552 100644 --- a/include/libdecnumber/decDPD.h +++ b/include/libdecnumber/decDPD.h @@ -24,9 +24,8 @@ for more details. You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING. If not, write to the Free - Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. */ + along with GCC; see the file COPYING. If not, see + <https://www.gnu.org/licenses/>. */ /* ------------------------------------------------------------------------ */ /* Binary Coded Decimal and Densely Packed Decimal conversion lookup tables */ diff --git a/include/libdecnumber/decNumber.h b/include/libdecnumber/decNumber.h index 41bc2a0..bf37af8 100644 --- a/include/libdecnumber/decNumber.h +++ b/include/libdecnumber/decNumber.h @@ -24,9 +24,8 @@ for more details. You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING. If not, write to the Free - Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. */ + along with GCC; see the file COPYING. If not, see + <https://www.gnu.org/licenses/>. */ /* ------------------------------------------------------------------ */ /* Decimal Number arithmetic module header */ diff --git a/include/libdecnumber/decNumberLocal.h b/include/libdecnumber/decNumberLocal.h index 6198ca8..0959f66 100644 --- a/include/libdecnumber/decNumberLocal.h +++ b/include/libdecnumber/decNumberLocal.h @@ -24,9 +24,8 @@ for more details. You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING. If not, write to the Free - Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. */ + along with GCC; see the file COPYING. If not, see + <https://www.gnu.org/licenses/>. */ /* ------------------------------------------------------------------ */ /* decNumber package local type, tuning, and macro definitions */ diff --git a/include/libdecnumber/dpd/decimal128.h b/include/libdecnumber/dpd/decimal128.h index aff261e..c57180b 100644 --- a/include/libdecnumber/dpd/decimal128.h +++ b/include/libdecnumber/dpd/decimal128.h @@ -24,9 +24,8 @@ for more details. You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING. If not, write to the Free - Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. */ + along with GCC; see the file COPYING. If not, see + <https://www.gnu.org/licenses/>. */ /* ------------------------------------------------------------------ */ /* Decimal 128-bit format module header */ diff --git a/include/libdecnumber/dpd/decimal128Local.h b/include/libdecnumber/dpd/decimal128Local.h index 9765427..2948ab2 100644 --- a/include/libdecnumber/dpd/decimal128Local.h +++ b/include/libdecnumber/dpd/decimal128Local.h @@ -23,9 +23,8 @@ for more details. You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING. If not, write to the Free - Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. */ + along with GCC; see the file COPYING. If not, see + <https://www.gnu.org/licenses/>. */ #if !defined(DECIMAL128LOCAL) diff --git a/include/libdecnumber/dpd/decimal32.h b/include/libdecnumber/dpd/decimal32.h index 6cb9e43..9a17933 100644 --- a/include/libdecnumber/dpd/decimal32.h +++ b/include/libdecnumber/dpd/decimal32.h @@ -24,9 +24,8 @@ for more details. You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING. If not, write to the Free - Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. */ + along with GCC; see the file COPYING. If not, see + <https://www.gnu.org/licenses/>. */ /* ------------------------------------------------------------------ */ /* Decimal 32-bit format module header */ diff --git a/include/libdecnumber/dpd/decimal64.h b/include/libdecnumber/dpd/decimal64.h index f29e570..5c3d0bb 100644 --- a/include/libdecnumber/dpd/decimal64.h +++ b/include/libdecnumber/dpd/decimal64.h @@ -24,9 +24,8 @@ for more details. You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING. If not, write to the Free - Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. */ + along with GCC; see the file COPYING. If not, see + <https://www.gnu.org/licenses/>. */ /* ------------------------------------------------------------------ */ /* Decimal 64-bit format module header */ diff --git a/include/migration/blocker.h b/include/migration/blocker.h index a687ac0..80b75ad 100644 --- a/include/migration/blocker.h +++ b/include/migration/blocker.h @@ -16,8 +16,6 @@ #include "qapi/qapi-types-migration.h" -#define MIG_MODE_ALL MIG_MODE__MAX - /** * @migrate_add_blocker - prevent all modes of migration from proceeding * @@ -82,16 +80,15 @@ int migrate_add_blocker_normal(Error **reasonp, Error **errp); * * @reasonp - address of an error to be returned whenever migration is attempted * - * @errp - [out] The reason (if any) we cannot block migration right now. + * @modes - the migration modes to be blocked, a bit set of MigMode * - * @mode - one or more migration modes to be blocked. The list is terminated - * by -1 or MIG_MODE_ALL. For the latter, all modes are blocked. + * @errp - [out] The reason (if any) we cannot block migration right now. * * @returns - 0 on success, -EBUSY/-EACCES on failure, with errp set. * * *@reasonp is freed and set to NULL if failure is returned. * On success, the caller must not free *@reasonp before the blocker is removed. */ -int migrate_add_blocker_modes(Error **reasonp, Error **errp, MigMode mode, ...); +int migrate_add_blocker_modes(Error **reasonp, unsigned modes, Error **errp); #endif diff --git a/include/migration/colo.h b/include/migration/colo.h index 43222ef..d4fe422 100644 --- a/include/migration/colo.h +++ b/include/migration/colo.h @@ -25,7 +25,7 @@ void migrate_start_colo_process(MigrationState *s); bool migration_in_colo_state(void); /* loadvm */ -int migration_incoming_enable_colo(void); +int migration_incoming_enable_colo(Error **errp); void migration_incoming_disable_colo(void); bool migration_incoming_colo_enabled(void); bool migration_incoming_in_colo_state(void); diff --git a/include/migration/cpr.h b/include/migration/cpr.h index 7561fc7..027cb98 100644 --- a/include/migration/cpr.h +++ b/include/migration/cpr.h @@ -9,26 +9,55 @@ #define MIGRATION_CPR_H #include "qapi/qapi-types-migration.h" +#include "qemu/queue.h" #define MIG_MODE_NONE -1 #define QEMU_CPR_FILE_MAGIC 0x51435052 #define QEMU_CPR_FILE_VERSION 0x00000001 +#define CPR_STATE "CprState" + +typedef QLIST_HEAD(CprFdList, CprFd) CprFdList; +typedef QLIST_HEAD(CprVFIODeviceList, CprVFIODevice) CprVFIODeviceList; + +typedef struct CprState { + CprFdList fds; + CprVFIODeviceList vfio_devices; +} CprState; + +extern CprState cpr_state; void cpr_save_fd(const char *name, int id, int fd); void cpr_delete_fd(const char *name, int id); int cpr_find_fd(const char *name, int id); +void cpr_resave_fd(const char *name, int id, int fd); +int cpr_open_fd(const char *path, int flags, const char *name, int id, + Error **errp); + +typedef bool (*cpr_walk_fd_cb)(int fd); +bool cpr_walk_fd(cpr_walk_fd_cb cb); MigMode cpr_get_incoming_mode(void); void cpr_set_incoming_mode(MigMode mode); bool cpr_is_incoming(void); -int cpr_state_save(MigrationChannel *channel, Error **errp); +bool cpr_state_save(MigrationChannel *channel, Error **errp); int cpr_state_load(MigrationChannel *channel, Error **errp); void cpr_state_close(void); struct QIOChannel *cpr_state_ioc(void); +bool cpr_incoming_needed(void *opaque); +int cpr_get_fd_param(const char *name, const char *fdname, int index, + Error **errp); + QEMUFile *cpr_transfer_output(MigrationChannel *channel, Error **errp); QEMUFile *cpr_transfer_input(MigrationChannel *channel, Error **errp); +void cpr_exec_init(void); +QEMUFile *cpr_exec_output(Error **errp); +QEMUFile *cpr_exec_input(Error **errp); +bool cpr_exec_persist_state(QEMUFile *f, Error **errp); +bool cpr_exec_has_state(void); +void cpr_exec_unpersist_state(void); +void cpr_exec_unpreserve_fds(void); #endif diff --git a/include/migration/cpu.h b/include/migration/cpu.h index 65abe3c..ca7cc04 100644 --- a/include/migration/cpu.h +++ b/include/migration/cpu.h @@ -19,8 +19,6 @@ #define VMSTATE_UINTTL_V(_f, _s, _v) \ VMSTATE_UINT64_V(_f, _s, _v) -#define VMSTATE_UINTTL_EQUAL_V(_f, _s, _v) \ - VMSTATE_UINT64_EQUAL_V(_f, _s, _v) #define VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, _v) \ VMSTATE_UINT64_ARRAY_V(_f, _s, _n, _v) #define VMSTATE_UINTTL_2DARRAY_V(_f, _s, _n1, _n2, _v) \ @@ -40,8 +38,6 @@ #define VMSTATE_UINTTL_V(_f, _s, _v) \ VMSTATE_UINT32_V(_f, _s, _v) -#define VMSTATE_UINTTL_EQUAL_V(_f, _s, _v) \ - VMSTATE_UINT32_EQUAL_V(_f, _s, _v) #define VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, _v) \ VMSTATE_UINT32_ARRAY_V(_f, _s, _n, _v) #define VMSTATE_UINTTL_2DARRAY_V(_f, _s, _n1, _n2, _v) \ @@ -53,8 +49,6 @@ #define VMSTATE_UINTTL(_f, _s) \ VMSTATE_UINTTL_V(_f, _s, 0) -#define VMSTATE_UINTTL_EQUAL(_f, _s) \ - VMSTATE_UINTTL_EQUAL_V(_f, _s, 0) #define VMSTATE_UINTTL_ARRAY(_f, _s, _n) \ VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, 0) #define VMSTATE_UINTTL_2DARRAY(_f, _s, _n1, _n2) \ diff --git a/include/migration/misc.h b/include/migration/misc.h index 8fd36eb..e26d418 100644 --- a/include/migration/misc.h +++ b/include/migration/misc.h @@ -90,12 +90,24 @@ void migration_add_notifier(NotifierWithReturn *notify, MigrationNotifyFunc func); /* - * Same as migration_add_notifier, but applies to be specified @mode. + * Same as migration_add_notifier, but applies to the specified @mode + * instead of MIG_MODE_NORMAL. */ void migration_add_notifier_mode(NotifierWithReturn *notify, MigrationNotifyFunc func, MigMode mode); +/* + * Same as migration_add_notifier, but applies to the specified @modes + * (a bitset of MigMode). + */ +void migration_add_notifier_modes(NotifierWithReturn *notify, + MigrationNotifyFunc func, unsigned modes); + +/* + * Remove a notifier from all modes. + */ void migration_remove_notifier(NotifierWithReturn *notify); + void migration_file_set_error(int ret, Error *err); /* True if incoming migration entered POSTCOPY_INCOMING_DISCARD */ @@ -119,19 +131,19 @@ bool migrate_uri_parse(const char *uri, MigrationChannel **channel, Error **errp); /* migration/multifd-device-state.c */ -typedef struct SaveLiveCompletePrecopyThreadData { - SaveLiveCompletePrecopyThreadHandler hdlr; +typedef struct SaveCompletePrecopyThreadData { + SaveCompletePrecopyThreadHandler hdlr; char *idstr; uint32_t instance_id; void *handler_opaque; -} SaveLiveCompletePrecopyThreadData; +} SaveCompletePrecopyThreadData; bool multifd_queue_device_state(char *idstr, uint32_t instance_id, char *data, size_t len); bool multifd_device_state_supported(void); void -multifd_spawn_device_state_save_thread(SaveLiveCompletePrecopyThreadHandler hdlr, +multifd_spawn_device_state_save_thread(SaveCompletePrecopyThreadHandler hdlr, char *idstr, uint32_t instance_id, void *opaque); diff --git a/include/migration/register.h b/include/migration/register.h index b79dc81..ae79794 100644 --- a/include/migration/register.h +++ b/include/migration/register.h @@ -78,51 +78,43 @@ typedef struct SaveVMHandlers { void (*save_cleanup)(void *opaque); /** - * @save_live_complete_postcopy + * @save_complete * - * Called at the end of postcopy for all postcopyable devices. + * Transmits the last section for the device containing any + * remaining data at the end phase of migration. * - * @f: QEMUFile where to send the data - * @opaque: data pointer passed to register_savevm_live() + * For precopy, this will be invoked _during_ the switchover phase + * after source VM is stopped. * - * Returns zero to indicate success and negative for error - */ - int (*save_live_complete_postcopy)(QEMUFile *f, void *opaque); - - /** - * @save_live_complete_precopy - * - * Transmits the last section for the device containing any - * remaining data at the end of a precopy phase. When postcopy is - * enabled, devices that support postcopy will skip this step, - * where the final data will be flushed at the end of postcopy via - * @save_live_complete_postcopy instead. + * For postcopy, this will be invoked _after_ the switchover phase + * (except some very unusual cases, like PMEM ramblocks), while + * destination VM can be running. * * @f: QEMUFile where to send the data * @opaque: data pointer passed to register_savevm_live() * * Returns zero to indicate success and negative for error */ - int (*save_live_complete_precopy)(QEMUFile *f, void *opaque); + int (*save_complete)(QEMUFile *f, void *opaque); /** - * @save_live_complete_precopy_thread (invoked in a separate thread) + * @save_complete_precopy_thread (invoked in a separate thread) * * Called at the end of a precopy phase from a separate worker thread * in configurations where multifd device state transfer is supported * in order to perform asynchronous transmission of the remaining data in - * parallel with @save_live_complete_precopy handlers. + * parallel with @save_complete handlers. * When postcopy is enabled, devices that support postcopy will skip this * step. * - * @d: a #SaveLiveCompletePrecopyThreadData containing parameters that the + * @d: a #SaveCompletePrecopyThreadData containing parameters that the * handler may need, including this device section idstr and instance_id, * and opaque data pointer passed to register_savevm_live(). * @errp: pointer to Error*, to store an error if it happens. * * Returns true to indicate success and false for errors. */ - SaveLiveCompletePrecopyThreadHandler save_live_complete_precopy_thread; + SaveCompletePrecopyThreadHandler save_complete_precopy_thread; /* This runs both outside and inside the BQL. */ diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index a1dfab4..a87a5ef 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -155,10 +155,15 @@ enum VMStateFlags { }; typedef enum { - MIG_PRI_DEFAULT = 0, + MIG_PRI_UNINITIALIZED = 0, /* An uninitialized priority field maps to */ + /* MIG_PRI_DEFAULT in save_state_priority */ + + MIG_PRI_LOW, /* Must happen after default */ + MIG_PRI_DEFAULT, MIG_PRI_IOMMU, /* Must happen before PCI devices */ MIG_PRI_PCI_BUS, /* Must happen before IOMMU */ MIG_PRI_VIRTIO_MEM, /* Must happen before IOMMU */ + MIG_PRI_APIC, /* Must happen before PCI devices */ MIG_PRI_GICV3_ITS, /* Must happen before PCI devices */ MIG_PRI_GICV3, /* Must happen before the ITS */ MIG_PRI_MAX, @@ -196,14 +201,28 @@ struct VMStateDescription { * exclusive. For this reason, also early_setup VMSDs are migrated in a * QEMU_VM_SECTION_FULL section, while save_setup() data is migrated in * a QEMU_VM_SECTION_START section. + * + * There are duplicate impls of the post/pre save/load hooks. + * New impls should preferentally use 'errp' variants of these + * methods and existing impls incrementally converted. + * The variants without 'errp' are intended to be removed + * once all usage is converted. + * + * For the errp variants, + * Returns: 0 on success, + * <0 on error where -value is an error number from errno.h */ + bool early_setup; int version_id; int minimum_version_id; MigrationPriority priority; int (*pre_load)(void *opaque); + bool (*pre_load_errp)(void *opaque, Error **errp); int (*post_load)(void *opaque, int version_id); + bool (*post_load_errp)(void *opaque, int version_id, Error **errp); int (*pre_save)(void *opaque); + bool (*pre_save_errp)(void *opaque, Error **errp); int (*post_save)(void *opaque); bool (*needed)(void *opaque); bool (*dev_unplug_pending)(void *opaque); @@ -518,6 +537,16 @@ extern const VMStateInfo vmstate_info_qlist; .offset = vmstate_offset_array(_s, _f, _type*, _n), \ } +#define VMSTATE_VARRAY_OF_POINTER_UINT32(_field, _state, _field_num, _version, _info, _type) { \ + .name = (stringify(_field)), \ + .version_id = (_version), \ + .num_offset = vmstate_offset_value(_state, _field_num, uint32_t), \ + .info = &(_info), \ + .size = sizeof(_type), \ + .flags = VMS_VARRAY_UINT32 | VMS_ARRAY_OF_POINTER | VMS_POINTER, \ + .offset = vmstate_offset_pointer(_state, _field, _type), \ +} + #define VMSTATE_STRUCT_SUB_ARRAY(_field, _state, _start, _num, _version, _vmsd, _type) { \ .name = (stringify(_field)), \ .version_id = (_version), \ @@ -703,7 +732,7 @@ extern const VMStateInfo vmstate_info_qlist; .version_id = (_version), \ .size = (_size), \ .info = &vmstate_info_buffer, \ - .flags = VMS_BUFFER|VMS_POINTER, \ + .flags = VMS_BUFFER | VMS_POINTER, \ .offset = offsetof(_state, _field), \ } @@ -1192,10 +1221,8 @@ extern const VMStateInfo vmstate_info_qlist; } int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, - void *opaque, int version_id); + void *opaque, int version_id, Error **errp); int vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd, - void *opaque, JSONWriter *vmdesc); -int vmstate_save_state_with_err(QEMUFile *f, const VMStateDescription *vmsd, void *opaque, JSONWriter *vmdesc, Error **errp); int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd, void *opaque, JSONWriter *vmdesc, diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h index ae116d9..83721b5 100644 --- a/include/monitor/hmp.h +++ b/include/monitor/hmp.h @@ -24,6 +24,7 @@ strList *hmp_split_at_comma(const char *str); void hmp_info_name(Monitor *mon, const QDict *qdict); void hmp_info_version(Monitor *mon, const QDict *qdict); void hmp_info_kvm(Monitor *mon, const QDict *qdict); +void hmp_info_accelerators(Monitor *mon, const QDict *qdict); void hmp_info_status(Monitor *mon, const QDict *qdict); void hmp_info_uuid(Monitor *mon, const QDict *qdict); void hmp_info_chardev(Monitor *mon, const QDict *qdict); @@ -178,5 +179,6 @@ void hmp_boot_set(Monitor *mon, const QDict *qdict); void hmp_info_mtree(Monitor *mon, const QDict *qdict); void hmp_info_cryptodev(Monitor *mon, const QDict *qdict); void hmp_dumpdtb(Monitor *mon, const QDict *qdict); +void hmp_info_firmware_log(Monitor *mon, const QDict *qdict); #endif diff --git a/include/monitor/qdev.h b/include/monitor/qdev.h index 1d57bf6..de33637 100644 --- a/include/monitor/qdev.h +++ b/include/monitor/qdev.h @@ -1,6 +1,8 @@ #ifndef MONITOR_QDEV_H #define MONITOR_QDEV_H +#include "hw/qdev-core.h" + /*** monitor commands ***/ void hmp_info_qtree(Monitor *mon, const QDict *qdict); @@ -11,6 +13,7 @@ int qdev_device_help(QemuOpts *opts); DeviceState *qdev_device_add(QemuOpts *opts, Error **errp); DeviceState *qdev_device_add_from_qdict(const QDict *opts, bool from_json, Error **errp); +BusState *qdev_find_default_bus(DeviceClass *dc, Error **errp); /** * qdev_set_id: parent the device and set its id if provided. diff --git a/include/net/can_emu.h b/include/net/can_emu.h index 6f9b206..777281b 100644 --- a/include/net/can_emu.h +++ b/include/net/can_emu.h @@ -85,7 +85,9 @@ typedef struct qemu_can_filter { #define QEMU_CAN_INV_FILTER 0x20000000U typedef struct CanBusClientState CanBusClientState; -typedef struct CanBusState CanBusState; + +#define TYPE_CAN_BUS "can-bus" +OBJECT_DECLARE_SIMPLE_TYPE(CanBusState, CAN_BUS) typedef struct CanBusClientInfo { bool (*can_receive)(CanBusClientState *); @@ -105,9 +107,6 @@ struct CanBusClientState { bool fd_mode; }; -#define TYPE_CAN_BUS "can-bus" -OBJECT_DECLARE_SIMPLE_TYPE(CanBusState, CAN_BUS) - int can_bus_filter_match(struct qemu_can_filter *filter, qemu_canid_t can_id); int can_bus_insert_client(CanBusState *bus, CanBusClientState *client); diff --git a/include/net/net.h b/include/net/net.h index cdd5b10..72b476e 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -35,6 +35,18 @@ typedef struct NICConf { int32_t bootindex; } NICConf; +typedef struct NetOffloads { + bool csum; + bool tso4; + bool tso6; + bool ecn; + bool ufo; + bool uso4; + bool uso6; + bool tnl; + bool tnl_csum; +} NetOffloads; + #define DEFINE_NIC_PROPERTIES(_state, _conf) \ DEFINE_PROP_MACADDR("mac", _state, _conf.macaddr), \ DEFINE_PROP_NETDEV("netdev", _state, _conf.peers) @@ -55,11 +67,13 @@ typedef void (NetClientDestructor)(NetClientState *); typedef RxFilterInfo *(QueryRxFilter)(NetClientState *); typedef bool (HasUfo)(NetClientState *); typedef bool (HasUso)(NetClientState *); +typedef bool (HasTunnel)(NetClientState *); typedef bool (HasVnetHdr)(NetClientState *); typedef bool (HasVnetHdrLen)(NetClientState *, int); -typedef void (SetOffload)(NetClientState *, int, int, int, int, int, int, int); +typedef void (SetOffload)(NetClientState *, const NetOffloads *); typedef int (GetVnetHdrLen)(NetClientState *); typedef void (SetVnetHdrLen)(NetClientState *, int); +typedef bool (GetVnetHashSupportedTypes)(NetClientState *, uint32_t *); typedef int (SetVnetLE)(NetClientState *, bool); typedef int (SetVnetBE)(NetClientState *, bool); typedef struct SocketReadState SocketReadState; @@ -67,6 +81,7 @@ typedef void (SocketReadStateFinalize)(SocketReadState *rs); typedef void (NetAnnounce)(NetClientState *); typedef bool (SetSteeringEBPF)(NetClientState *, int); typedef bool (NetCheckPeerType)(NetClientState *, ObjectClass *, Error **); +typedef struct vhost_net *(GetVHostNet)(NetClientState *nc); typedef struct NetClientInfo { NetClientDriver type; @@ -83,15 +98,18 @@ typedef struct NetClientInfo { NetPoll *poll; HasUfo *has_ufo; HasUso *has_uso; + HasTunnel *has_tunnel; HasVnetHdr *has_vnet_hdr; HasVnetHdrLen *has_vnet_hdr_len; SetOffload *set_offload; SetVnetHdrLen *set_vnet_hdr_len; SetVnetLE *set_vnet_le; SetVnetBE *set_vnet_be; + GetVnetHashSupportedTypes *get_vnet_hash_supported_types; NetAnnounce *announce; SetSteeringEBPF *set_steering_ebpf; NetCheckPeerType *check_peer_type; + GetVHostNet *get_vhost_net; } NetClientInfo; struct NetClientState { @@ -183,12 +201,13 @@ void qemu_set_info_str(NetClientState *nc, void qemu_format_nic_info_str(NetClientState *nc, uint8_t macaddr[6]); bool qemu_has_ufo(NetClientState *nc); bool qemu_has_uso(NetClientState *nc); +bool qemu_has_tunnel(NetClientState *nc); bool qemu_has_vnet_hdr(NetClientState *nc); bool qemu_has_vnet_hdr_len(NetClientState *nc, int len); -void qemu_set_offload(NetClientState *nc, int csum, int tso4, int tso6, - int ecn, int ufo, int uso4, int uso6); +void qemu_set_offload(NetClientState *nc, const NetOffloads *ol); int qemu_get_vnet_hdr_len(NetClientState *nc); void qemu_set_vnet_hdr_len(NetClientState *nc, int len); +bool qemu_get_vnet_hash_supported_types(NetClientState *nc, uint32_t *types); int qemu_set_vnet_le(NetClientState *nc, bool is_le); int qemu_set_vnet_be(NetClientState *nc, bool is_be); void qemu_macaddr_default_if_unset(MACAddr *macaddr); @@ -298,6 +317,7 @@ void net_client_parse(QemuOptsList *opts_list, const char *optstr); void show_netdevs(void); void net_init_clients(void); void net_check_clients(void); +void net_client_set_link(NetClientState **ncs, int queues, bool up); void net_cleanup(void); void hmp_host_net_add(Monitor *mon, const QDict *qdict); void hmp_host_net_remove(Monitor *mon, const QDict *qdict); diff --git a/include/net/tap.h b/include/net/tap.h index 5d58551..6f34f13 100644 --- a/include/net/tap.h +++ b/include/net/tap.h @@ -33,7 +33,4 @@ int tap_disable(NetClientState *nc); int tap_get_fd(NetClientState *nc); -struct vhost_net; -struct vhost_net *tap_get_vhost_net(NetClientState *nc); - #endif /* QEMU_NET_TAP_H */ diff --git a/include/net/vhost-user.h b/include/net/vhost-user.h deleted file mode 100644 index 35bf619..0000000 --- a/include/net/vhost-user.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * vhost-user.h - * - * Copyright (c) 2013 Virtual Open Systems Sarl. - * - * 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 VHOST_USER_H -#define VHOST_USER_H - -struct vhost_net; -struct vhost_net *vhost_user_get_vhost_net(NetClientState *nc); -uint64_t vhost_user_get_acked_features(NetClientState *nc); -void vhost_user_save_acked_features(NetClientState *nc); - -#endif /* VHOST_USER_H */ diff --git a/include/net/vhost-vdpa.h b/include/net/vhost-vdpa.h index b81f9a6..f8d7d6c 100644 --- a/include/net/vhost-vdpa.h +++ b/include/net/vhost-vdpa.h @@ -14,8 +14,4 @@ #define TYPE_VHOST_VDPA "vhost-vdpa" -struct vhost_net *vhost_vdpa_get_vhost_net(NetClientState *nc); - -extern const int vdpa_feature_bits[]; - #endif /* VHOST_VDPA_H */ diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h index c6a5361..0225207 100644 --- a/include/net/vhost_net.h +++ b/include/net/vhost_net.h @@ -2,16 +2,25 @@ #define VHOST_NET_H #include "net/net.h" +#include "hw/virtio/virtio-features.h" #include "hw/virtio/vhost-backend.h" struct vhost_net; typedef struct vhost_net VHostNetState; +typedef uint64_t (GetAckedFeatures)(NetClientState *nc); +typedef void (SaveAcketFeatures)(NetClientState *nc); + typedef struct VhostNetOptions { VhostBackendType backend_type; NetClientState *net_backend; uint32_t busyloop_timeout; unsigned int nvqs; + const int *feature_bits; + int max_tx_queue_size; + bool is_vhost_user; + GetAckedFeatures *get_acked_features; + SaveAcketFeatures *save_acked_features; void *opaque; } VhostNetOptions; @@ -25,8 +34,26 @@ void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs, void vhost_net_cleanup(VHostNetState *net); -uint64_t vhost_net_get_features(VHostNetState *net, uint64_t features); -void vhost_net_ack_features(VHostNetState *net, uint64_t features); +void vhost_net_get_features_ex(VHostNetState *net, uint64_t *features); +static inline uint64_t vhost_net_get_features(VHostNetState *net, + uint64_t features) +{ + uint64_t features_array[VIRTIO_FEATURES_NU64S]; + + virtio_features_from_u64(features_array, features); + vhost_net_get_features_ex(net, features_array); + return features_array[0]; +} + +void vhost_net_ack_features_ex(VHostNetState *net, const uint64_t *features); +static inline void vhost_net_ack_features(VHostNetState *net, + uint64_t features) +{ + uint64_t features_array[VIRTIO_FEATURES_NU64S]; + + virtio_features_from_u64(features_array, features); + vhost_net_ack_features_ex(net, features_array); +} int vhost_net_get_config(struct vhost_net *net, uint8_t *config, uint32_t config_len); @@ -41,9 +68,17 @@ void vhost_net_config_mask(VHostNetState *net, VirtIODevice *dev, bool mask); int vhost_net_notify_migration_done(VHostNetState *net, char* mac_addr); VHostNetState *get_vhost_net(NetClientState *nc); -int vhost_set_vring_enable(NetClientState * nc, int enable); +int vhost_net_set_vring_enable(NetClientState *nc, int enable); + +void vhost_net_get_acked_features_ex(VHostNetState *net, uint64_t *features); +static inline uint64_t vhost_net_get_acked_features(VHostNetState *net) +{ + uint64_t features[VIRTIO_FEATURES_NU64S]; -uint64_t vhost_net_get_acked_features(VHostNetState *net); + vhost_net_get_acked_features_ex(net, features); + assert(!virtio_features_use_ex(features)); + return features[0]; +} int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu); diff --git a/include/qapi/error-internal.h b/include/qapi/error-internal.h new file mode 100644 index 0000000..ff18a20 --- /dev/null +++ b/include/qapi/error-internal.h @@ -0,0 +1,35 @@ +/* + * QEMU Error Objects - struct definition + * + * Copyright IBM, Corp. 2011 + * Copyright (C) 2011-2015 Red Hat, Inc. + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * Markus Armbruster <armbru@redhat.com>, + * + * This work is licensed under the terms of the GNU LGPL, version 2. See + * the COPYING.LIB file in the top-level directory. + */ + +#ifndef QAPI_ERROR_INTERNAL_H + +struct Error +{ + char *msg; + ErrorClass err_class; + + /* Used for error_abort only, may be NULL. */ + const char *func; + + /* + * src might be NUL-terminated or not. If it is, src_len is negative. + * If it is not, src_len is the length. + */ + const char *src; + int src_len; + int line; + GString *hint; +}; + +#endif diff --git a/include/qapi/error.h b/include/qapi/error.h index 41e3816..b16c630 100644 --- a/include/qapi/error.h +++ b/include/qapi/error.h @@ -534,12 +534,6 @@ static inline void error_propagator_cleanup(ErrorPropagator *prop) G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(ErrorPropagator, error_propagator_cleanup); /* - * Special error destination to warn on error. - * See error_setg() and error_propagate() for details. - */ -extern Error *error_warn; - -/* * Special error destination to abort on error. * See error_setg() and error_propagate() for details. */ diff --git a/include/qemu/accel.h b/include/qemu/accel.h index fbd3d89..d3638c7 100644 --- a/include/qemu/accel.h +++ b/include/qemu/accel.h @@ -26,39 +26,8 @@ #include "qom/object.h" #include "exec/hwaddr.h" -struct AccelState { - /*< private >*/ - Object parent_obj; -}; - -typedef struct AccelClass { - /*< private >*/ - ObjectClass parent_class; - /*< public >*/ - - const char *name; - int (*init_machine)(MachineState *ms); - bool (*cpu_common_realize)(CPUState *cpu, Error **errp); - void (*cpu_common_unrealize)(CPUState *cpu); - - /* system related hooks */ - void (*setup_post)(MachineState *ms, AccelState *accel); - bool (*has_memory)(MachineState *ms, AddressSpace *as, - hwaddr start_addr, hwaddr size); - - /* gdbstub related hooks */ - int (*gdbstub_supported_sstep_flags)(void); - - bool *allowed; - /* - * Array of global properties that would be applied when specific - * accelerator is chosen. It works like MachineClass.compat_props - * but it's for accelerators not machines. Accelerator-provided - * global properties may be overridden by machine-type - * compat_props or user-provided global properties. - */ - GPtrArray *compat_props; -} AccelClass; +typedef struct AccelState AccelState; +typedef struct AccelClass AccelClass; #define TYPE_ACCEL "accel" @@ -83,6 +52,8 @@ 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. diff --git a/include/qemu/audio-capture.h b/include/qemu/audio-capture.h new file mode 100644 index 0000000..a07412d --- /dev/null +++ b/include/qemu/audio-capture.h @@ -0,0 +1,43 @@ +/* + * QEMU Audio subsystem + * + * SPDX-License-Identifier: MIT + */ +#ifndef QEMU_AUDIO_CAPTURE_H +#define QEMU_AUDIO_CAPTURE_H + +#include "audio.h" + +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); +}; + +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 *AUD_add_capture( + AudioBackend *be, + struct audsettings *as, + struct audio_capture_ops *ops, + void *opaque + ); +void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque); + +#endif /* QEMU_AUDIO_CAPTURE_H */ diff --git a/include/qemu/audio.h b/include/qemu/audio.h new file mode 100644 index 0000000..c56af89 --- /dev/null +++ b/include/qemu/audio.h @@ -0,0 +1,150 @@ +/* + * 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/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; + int endianness; +} audsettings; + +typedef struct SWVoiceOut SWVoiceOut; +typedef struct SWVoiceIn SWVoiceIn; + +struct AudioBackendClass { + ObjectClass parent_class; +}; + +typedef struct AudioBackend AudioBackend; + +typedef struct QEMUAudioTimeStamp { + uint64_t old_ts; +} QEMUAudioTimeStamp; + +bool AUD_backend_check(AudioBackend **be, Error **errp); + +SWVoiceOut *AUD_open_out ( + AudioBackend *be, + SWVoiceOut *sw, + const char *name, + void *callback_opaque, + audio_callback_fn callback_fn, + struct audsettings *settings + ); + +void AUD_close_out (AudioBackend *be, SWVoiceOut *sw); +size_t AUD_write (SWVoiceOut *sw, void *pcm_buf, size_t size); +int AUD_get_buffer_size_out (SWVoiceOut *sw); +void AUD_set_active_out(SWVoiceOut *sw, bool on); +bool AUD_is_active_out(SWVoiceOut *sw); + +void AUD_init_time_stamp_out (SWVoiceOut *sw, QEMUAudioTimeStamp *ts); +uint64_t AUD_get_elapsed_usec_out (SWVoiceOut *sw, QEMUAudioTimeStamp *ts); + +#define AUDIO_MAX_CHANNELS 16 +typedef struct Volume { + bool mute; + int channels; + uint8_t vol[AUDIO_MAX_CHANNELS]; +} Volume; + +void AUD_set_volume_out(SWVoiceOut *sw, Volume *vol); +void AUD_set_volume_in(SWVoiceIn *sw, Volume *vol); + +static inline void +AUD_set_volume_out_lr(SWVoiceOut *sw, bool mut, uint8_t lvol, uint8_t rvol) { + AUD_set_volume_out(sw, &(Volume) { + .mute = mut, .channels = 2, .vol = { lvol, rvol } + }); +} + +static inline void +AUD_set_volume_in_lr(SWVoiceIn *sw, bool mut, uint8_t lvol, uint8_t rvol) { + AUD_set_volume_in(sw, &(Volume) { + .mute = mut, .channels = 2, .vol = { lvol, rvol } + }); +} + +SWVoiceIn *AUD_open_in( + AudioBackend *be, + SWVoiceIn *sw, + const char *name, + void *callback_opaque, + audio_callback_fn callback_fn, + struct audsettings *settings + ); + +void AUD_close_in(AudioBackend *be, SWVoiceIn *sw); +size_t AUD_read (SWVoiceIn *sw, void *pcm_buf, size_t size); +void AUD_set_active_in(SWVoiceIn *sw, bool on); +bool AUD_is_active_in(SWVoiceIn *sw); + +void AUD_init_time_stamp_in (SWVoiceIn *sw, QEMUAudioTimeStamp *ts); +uint64_t AUD_get_elapsed_usec_in (SWVoiceIn *sw, QEMUAudioTimeStamp *ts); + +void audio_cleanup(void); + +typedef struct st_sample st_sample; + +void audio_sample_to_uint64(const st_sample *sample, int pos, + uint64_t *left, uint64_t *right); +void audio_sample_from_uint64(st_sample *sample, int pos, + uint64_t left, uint64_t right); + +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_set_dbus_server(AudioBackend *be, + GDBusObjectManagerServer *server, + bool p2p, + Error **errp); +#endif + +#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 */ diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h index 9a11764..39ba640 100644 --- a/include/qemu/bswap.h +++ b/include/qemu/bswap.h @@ -1,6 +1,8 @@ #ifndef BSWAP_H #define BSWAP_H +#include "qemu/target-info.h" + #undef bswap16 #define bswap16(_x) __builtin_bswap16(_x) #undef bswap32 @@ -432,4 +434,75 @@ DO_STN_LDN_P(be) #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 */ diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h index 496dac5..1c2b673 100644 --- a/include/qemu/compiler.h +++ b/include/qemu/compiler.h @@ -182,19 +182,6 @@ #define QEMU_DISABLE_CFI #endif -/* - * Apple clang version 14 has a bug in its __builtin_subcll(); define - * BUILTIN_SUBCLL_BROKEN for the offending versions so we can avoid it. - * When a version of Apple clang which has this bug fixed is released - * we can add an upper bound to this check. - * See https://gitlab.com/qemu-project/qemu/-/issues/1631 - * and https://gitlab.com/qemu-project/qemu/-/issues/1659 for details. - * The bug never made it into any upstream LLVM releases, only Apple ones. - */ -#if defined(__apple_build_version__) && __clang_major__ >= 14 -#define BUILTIN_SUBCLL_BROKEN -#endif - #if __has_attribute(annotate) #define QEMU_ANNOTATE(x) __attribute__((annotate(x))) #else @@ -208,6 +195,26 @@ #endif /* + * 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. diff --git a/include/qemu/cpuid.h b/include/qemu/cpuid.h index b111615..de7a9005 100644 --- a/include/qemu/cpuid.h +++ b/include/qemu/cpuid.h @@ -68,6 +68,9 @@ #ifndef bit_AVX512VBMI2 #define bit_AVX512VBMI2 (1 << 6) #endif +#ifndef bit_GFNI +#define bit_GFNI (1 << 8) +#endif /* Leaf 0x80000001, %ecx */ #ifndef bit_LZCNT diff --git a/include/qemu/exit-with-parent.h b/include/qemu/exit-with-parent.h new file mode 100644 index 0000000..c00b863 --- /dev/null +++ b/include/qemu/exit-with-parent.h @@ -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 */ diff --git a/include/qemu/futex.h b/include/qemu/futex.h index 91ae889..607613e 100644 --- a/include/qemu/futex.h +++ b/include/qemu/futex.h @@ -1,5 +1,5 @@ /* - * Wrappers around Linux futex syscall + * Wrappers around Linux futex syscall and similar * * Copyright Red Hat, Inc. 2017 * @@ -11,17 +11,35 @@ * */ +/* + * 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(void *f, int n) +static inline void qemu_futex_wake_all(void *f) { - qemu_futex(f, FUTEX_WAKE, n, NULL, NULL, 0); + 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) @@ -37,5 +55,25 @@ static inline void qemu_futex_wait(void *f, unsigned val) } } } +#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 */ diff --git a/include/qemu/host-utils.h b/include/qemu/host-utils.h index 4d28fa2..dd55858 100644 --- a/include/qemu/host-utils.h +++ b/include/qemu/host-utils.h @@ -677,7 +677,7 @@ static inline uint64_t uadd64_carry(uint64_t x, uint64_t y, bool *pcarry) */ static inline uint64_t usub64_borrow(uint64_t x, uint64_t y, bool *pborrow) { -#if __has_builtin(__builtin_subcll) && !defined(BUILTIN_SUBCLL_BROKEN) +#if __has_builtin(__builtin_subcll) unsigned long long b = *pborrow; x = __builtin_subcll(x, y, b, &b); *pborrow = b & 1; diff --git a/include/qemu/job.h b/include/qemu/job.h index a5a0415..ead3157 100644 --- a/include/qemu/job.h +++ b/include/qemu/job.h @@ -263,7 +263,7 @@ struct JobDriver { * This callback will not be invoked if the job has already failed. * If it fails, abort and then clean will be called. */ - int (*prepare)(Job *job); + int GRAPH_UNLOCKED_PTR (*prepare)(Job *job); /** * If the callback is not NULL, it will be invoked when all the jobs @@ -283,7 +283,7 @@ struct JobDriver { * All jobs will complete with a call to either .commit() or .abort() but * never both. */ - void (*abort)(Job *job); + void GRAPH_UNLOCKED_PTR (*abort)(Job *job); /** * If the callback is not NULL, it will be invoked after a call to either diff --git a/include/qemu/lockcnt.h b/include/qemu/lockcnt.h index f4b62a3..5a2800e 100644 --- a/include/qemu/lockcnt.h +++ b/include/qemu/lockcnt.h @@ -17,7 +17,7 @@ typedef struct QemuLockCnt QemuLockCnt; struct QemuLockCnt { -#ifndef CONFIG_LINUX +#ifndef HAVE_FUTEX QemuMutex mutex; #endif unsigned count; diff --git a/include/qemu/log-for-trace.h b/include/qemu/log-for-trace.h index d47c9cd..f3a8791 100644 --- a/include/qemu/log-for-trace.h +++ b/include/qemu/log-for-trace.h @@ -19,9 +19,9 @@ #define QEMU_LOG_FOR_TRACE_H /* Private global variable, don't use */ -extern int qemu_loglevel; +extern unsigned qemu_loglevel; -#define LOG_TRACE (1 << 15) +#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) diff --git a/include/qemu/log.h b/include/qemu/log.h index 60da703..7effba4 100644 --- a/include/qemu/log.h +++ b/include/qemu/log.h @@ -14,30 +14,30 @@ 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 (1 << 0) -#define CPU_LOG_TB_IN_ASM (1 << 1) -#define CPU_LOG_TB_OP (1 << 2) -#define CPU_LOG_TB_OP_OPT (1 << 3) -#define CPU_LOG_INT (1 << 4) -#define CPU_LOG_EXEC (1 << 5) -#define CPU_LOG_PCALL (1 << 6) -#define CPU_LOG_TB_CPU (1 << 8) -#define CPU_LOG_RESET (1 << 9) -#define LOG_UNIMP (1 << 10) -#define LOG_GUEST_ERROR (1 << 11) -#define CPU_LOG_MMU (1 << 12) -#define CPU_LOG_TB_NOCHAIN (1 << 13) -#define CPU_LOG_PAGE (1 << 14) +#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 (1 << 16) -#define CPU_LOG_TB_FPU (1 << 17) -#define CPU_LOG_PLUGIN (1 << 18) +#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 (1 << 19) -#define LOG_PER_THREAD (1 << 20) -#define CPU_LOG_TB_VPU (1 << 21) -#define LOG_TB_OP_PLUGIN (1 << 22) -#define LOG_INVALID_MEM (1 << 23) +#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. */ @@ -84,6 +84,8 @@ typedef struct 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); diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h index 4e2436b..0d55c63 100644 --- a/include/qemu/main-loop.h +++ b/include/qemu/main-loop.h @@ -271,6 +271,24 @@ void rust_bql_mock_lock(void); 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 diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index 96fe51b..3cb45a1 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -133,6 +133,20 @@ QEMU_EXTERN_C int daemon(int, int); #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 @@ -553,7 +567,7 @@ int madvise(char *, size_t, int); #if defined(__linux__) && \ (defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) \ - || defined(__powerpc64__)) + || 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. */ @@ -679,6 +693,16 @@ 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. diff --git a/include/qemu/plugin-event.h b/include/qemu/plugin-event.h index 7056d84..1100dae 100644 --- a/include/qemu/plugin-event.h +++ b/include/qemu/plugin-event.h @@ -20,6 +20,9 @@ enum qemu_plugin_event { 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_MAX, /* total number of plugin events we support */ }; diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h index 9726a9e..cea0a68 100644 --- a/include/qemu/plugin.h +++ b/include/qemu/plugin.h @@ -59,6 +59,7 @@ union qemu_plugin_cb_sig { qemu_plugin_udata_cb_t udata; qemu_plugin_vcpu_simple_cb_t vcpu_simple; 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; @@ -160,6 +161,9 @@ 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, @@ -209,6 +213,21 @@ void qemu_plugin_user_prefork_lock(void); */ 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) @@ -242,6 +261,15 @@ 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, diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h index 3a850aa..60de4fd 100644 --- a/include/qemu/qemu-plugin.h +++ b/include/qemu/qemu-plugin.h @@ -65,11 +65,18 @@ typedef uint64_t qemu_plugin_id_t; * * version 4: * - added qemu_plugin_read_memory_vaddr + * + * version 5: + * - added qemu_plugin_write_memory_vaddr + * - added qemu_plugin_read_memory_hwaddr + * - added qemu_plugin_write_memory_hwaddr + * - added qemu_plugin_write_register + * - added qemu_plugin_translate_vaddr */ extern QEMU_PLUGIN_EXPORT int qemu_plugin_version; -#define QEMU_PLUGIN_VERSION 4 +#define QEMU_PLUGIN_VERSION 5 /** * struct qemu_info_t - system information for plugins @@ -154,6 +161,50 @@ typedef void (*qemu_plugin_vcpu_simple_cb_t)(qemu_plugin_id_t id, typedef void (*qemu_plugin_vcpu_udata_cb_t)(unsigned int vcpu_index, void *userdata); + +/** + * enum qemu_plugin_discon_type - type of a (potential) PC discontinuity + * + * @QEMU_PLUGIN_DISCON_INTERRUPT: an interrupt, defined across all architectures + * as an asynchronous event, usually originating + * from outside the CPU + * @QEMU_PLUGIN_DISCON_EXCEPTION: an exception, defined across all architectures + * as a synchronous event in response to a + * specific instruction being executed + * @QEMU_PLUGIN_DISCON_HOSTCALL: a host call, functionally a special kind of + * exception that is not handled by code run by + * the vCPU but machinery outside the vCPU + * @QEMU_PLUGIN_DISCON_ALL: all types of disconinuity events currently covered + */ +enum qemu_plugin_discon_type { + QEMU_PLUGIN_DISCON_INTERRUPT = 1 << 0, + QEMU_PLUGIN_DISCON_EXCEPTION = 1 << 1, + QEMU_PLUGIN_DISCON_HOSTCALL = 1 << 2, + QEMU_PLUGIN_DISCON_ALL = -1 +}; + +/** + * typedef qemu_plugin_vcpu_discon_cb_t - vcpu discontinuity callback + * @id: plugin ID + * @vcpu_index: the current vcpu context + * @type: the type of discontinuity + * @from_pc: the source of the discontinuity, e.g. the PC before the + * transition + * @to_pc: the PC pointing to the next instruction to be executed + * + * The exact semantics of @from_pc depends on the @type of discontinuity. For + * interrupts, @from_pc will point to the next instruction which would have + * been executed. For exceptions and host calls, @from_pc will point to the + * instruction that caused the exception or issued the host call. Note that + * in the case of exceptions, the instruction may not be retired and thus not + * observable via general instruction exec callbacks. The same may be the case + * for some host calls such as hypervisor call "exceptions". + */ +typedef void (*qemu_plugin_vcpu_discon_cb_t)(qemu_plugin_id_t id, + unsigned int vcpu_index, + enum qemu_plugin_discon_type type, + uint64_t from_pc, uint64_t to_pc); + /** * qemu_plugin_uninstall() - Uninstall a plugin * @id: this plugin's opaque ID @@ -230,6 +281,22 @@ QEMU_PLUGIN_API void qemu_plugin_register_vcpu_resume_cb(qemu_plugin_id_t id, qemu_plugin_vcpu_simple_cb_t cb); +/** + * qemu_plugin_register_vcpu_discon_cb() - register a discontinuity callback + * @id: plugin ID + * @type: types of discontinuities for which to call the callback + * @cb: callback function + * + * The @cb function is called every time a vCPU receives a discontinuity event + * of the specified type(s), after the vCPU was prepared to handle the event. + * Preparation entails updating the PC, usually to some interrupt handler or + * trap vector entry. + */ +QEMU_PLUGIN_API +void qemu_plugin_register_vcpu_discon_cb(qemu_plugin_id_t id, + enum qemu_plugin_discon_type type, + qemu_plugin_vcpu_discon_cb_t cb); + /** struct qemu_plugin_tb - Opaque handle for a translation block */ struct qemu_plugin_tb; /** struct qemu_plugin_insn - Opaque handle for a translated instruction */ @@ -254,9 +321,6 @@ typedef struct { * @QEMU_PLUGIN_CB_NO_REGS: callback does not access the CPU's regs * @QEMU_PLUGIN_CB_R_REGS: callback reads the CPU's regs * @QEMU_PLUGIN_CB_RW_REGS: callback reads and writes the CPU's regs - * - * Note: currently QEMU_PLUGIN_CB_RW_REGS is unused, plugins cannot change - * system register state. */ enum qemu_plugin_cb_flags { QEMU_PLUGIN_CB_NO_REGS, @@ -871,7 +935,8 @@ struct qemu_plugin_register; /** * typedef qemu_plugin_reg_descriptor - register descriptions * - * @handle: opaque handle for retrieving value with qemu_plugin_read_register + * @handle: opaque handle for retrieving value with qemu_plugin_read_register or + * writing value with qemu_plugin_write_register * @name: register name * @feature: optional feature descriptor, can be NULL */ @@ -894,6 +959,51 @@ QEMU_PLUGIN_API GArray *qemu_plugin_get_registers(void); /** + * qemu_plugin_read_register() - read register for current vCPU + * + * @handle: a @qemu_plugin_reg_handle handle + * @buf: A GByteArray for the data owned by the plugin + * + * This function is only available in a context that register read access is + * explicitly requested via the QEMU_PLUGIN_CB_R_REGS flag, if called inside a + * callback that can be registered with a qemu_plugin_cb_flags argument. This + * function can also be used in any callback context that does not use a flags + * argument, such as in a callback registered with + * qemu_plugin_register_vcpu_init_cb(), except for callbacks registered with + * qemu_plugin_register_atexit_cb() and qemu_plugin_register_flush_cb(). + * + * Returns the size of the read register. The content of @buf is in target byte + * order. On failure returns -1. + */ +QEMU_PLUGIN_API +int qemu_plugin_read_register(struct qemu_plugin_register *handle, + GByteArray *buf); + +/** + * qemu_plugin_write_register() - write register for current vCPU + * + * @handle: a @qemu_plugin_reg_handle handle + * @buf: A GByteArray for the data owned by the plugin + * + * This function is only available in a context that register read access is + * explicitly requested via the QEMU_PLUGIN_CB_RW_REGS flag, if called inside a + * callback that can be registered with a qemu_plugin_cb_flags argument. This + * function can also be used in any callback context that does not use a flags + * argument, such as in a callback registered with + * qemu_plugin_register_vcpu_init_cb(), except for callbacks registered with + * qemu_plugin_register_atexit_cb() and qemu_plugin_register_flush_cb(). + * + * The size of @buf must be at least the size of the requested register. + * Attempting to write a register with @buf smaller than the register size + * will result in a crash or other undesired behavior. + * + * Returns the number of bytes written. On failure returns 0. + */ +QEMU_PLUGIN_API +int qemu_plugin_write_register(struct qemu_plugin_register *handle, + GByteArray *buf); + +/** * qemu_plugin_read_memory_vaddr() - read from memory using a virtual address * * @addr: A virtual address to read from @@ -916,20 +1026,118 @@ bool qemu_plugin_read_memory_vaddr(uint64_t addr, GByteArray *data, size_t len); /** - * qemu_plugin_read_register() - read register for current vCPU + * qemu_plugin_write_memory_vaddr() - write to memory using a virtual address * - * @handle: a @qemu_plugin_reg_handle handle - * @buf: A GByteArray for the data owned by the plugin + * @addr: A virtual address to write to + * @data: A byte array containing the data to write * - * This function is only available in a context that register read access is - * explicitly requested via the QEMU_PLUGIN_CB_R_REGS flag. + * The contents of @data will be written to memory starting at the virtual + * address @addr. * - * Returns the size of the read register. The content of @buf is in target byte - * order. On failure returns -1. + * This function does not guarantee consistency of writes, nor does it ensure + * that pending writes are flushed either before or after the write takes place, + * so callers should take care to only call this function in vCPU context (i.e. + * in callbacks) and avoid depending on the existence of data written using this + * function which may be overwritten afterward. + * + * Returns true on success and false on failure. */ QEMU_PLUGIN_API -int qemu_plugin_read_register(struct qemu_plugin_register *handle, - GByteArray *buf); +bool qemu_plugin_write_memory_vaddr(uint64_t addr, + GByteArray *data); + +/** + * enum qemu_plugin_hwaddr_operation_result - result of a memory operation + * + * @QEMU_PLUGIN_HWADDR_OPERATION_OK: hwaddr operation succeeded + * @QEMU_PLUGIN_HWADDR_OPERATION_ERROR: unexpected error occurred + * @QEMU_PLUGIN_HWADDR_OPERATION_DEVICE_ERROR: error in memory device + * @QEMU_PLUGIN_HWADDR_OPERATION_ACCESS_DENIED: permission error + * @QEMU_PLUGIN_HWADDR_OPERATION_INVALID_ADDRESS: address was invalid + * @QEMU_PLUGIN_HWADDR_OPERATION_INVALID_ADDRESS_SPACE: invalid address space + */ +enum qemu_plugin_hwaddr_operation_result { + QEMU_PLUGIN_HWADDR_OPERATION_OK, + QEMU_PLUGIN_HWADDR_OPERATION_ERROR, + QEMU_PLUGIN_HWADDR_OPERATION_DEVICE_ERROR, + QEMU_PLUGIN_HWADDR_OPERATION_ACCESS_DENIED, + QEMU_PLUGIN_HWADDR_OPERATION_INVALID_ADDRESS, + QEMU_PLUGIN_HWADDR_OPERATION_INVALID_ADDRESS_SPACE, +}; + +/** + * qemu_plugin_read_memory_hwaddr() - read from memory using a hardware address + * + * @addr: The physical address to read from + * @data: A byte array to store data into + * @len: The number of bytes to read, starting from @addr + * + * @len bytes of data is read from the current memory space for the current + * vCPU starting at @addr and stored into @data. If @data is not large enough to + * hold @len bytes, it will be expanded to the necessary size, reallocating if + * necessary. @len must be greater than 0. + * + * This function does not ensure writes are flushed prior to reading, so + * callers should take care when calling this function in plugin callbacks to + * avoid attempting to read data which may not yet be written and should use + * the memory callback API instead. + * + * This function is only valid for softmmu targets. + * + * Returns a qemu_plugin_hwaddr_operation_result indicating the result of the + * operation. + */ +QEMU_PLUGIN_API +enum qemu_plugin_hwaddr_operation_result +qemu_plugin_read_memory_hwaddr(uint64_t addr, GByteArray *data, size_t len); + +/** + * qemu_plugin_write_memory_hwaddr() - write to memory using a hardware address + * + * @addr: A physical address to write to + * @data: A byte array containing the data to write + * + * The contents of @data will be written to memory starting at the hardware + * address @addr in the current address space for the current vCPU. + * + * This function does not guarantee consistency of writes, nor does it ensure + * that pending writes are flushed either before or after the write takes place, + * so callers should take care when calling this function in plugin callbacks to + * avoid depending on the existence of data written using this function which + * may be overwritten afterward. In addition, this function requires that the + * pages containing the address are not locked. Practically, this means that you + * should not write instruction memory in a current translation block inside a + * callback registered with qemu_plugin_register_vcpu_tb_trans_cb. + * + * You can, for example, write instruction memory in a current translation block + * in a callback registered with qemu_plugin_register_vcpu_tb_exec_cb, although + * be aware that the write will not be flushed until after the translation block + * has finished executing. In general, this function should be used to write + * data memory or to patch code at a known address, not in a current translation + * block. + * + * This function is only valid for softmmu targets. + * + * Returns a qemu_plugin_hwaddr_operation_result indicating the result of the + * operation. + */ +QEMU_PLUGIN_API +enum qemu_plugin_hwaddr_operation_result +qemu_plugin_write_memory_hwaddr(uint64_t addr, GByteArray *data); + +/** + * qemu_plugin_translate_vaddr() - translate virtual address for current vCPU + * + * @vaddr: virtual address to translate + * @hwaddr: pointer to store the physical address + * + * This function is only valid in vCPU context (i.e. in callbacks) and is only + * valid for softmmu targets. + * + * Returns true on success and false on failure. + */ +QEMU_PLUGIN_API +bool qemu_plugin_translate_vaddr(uint64_t vaddr, uint64_t *hwaddr); /** * qemu_plugin_scoreboard_new() - alloc a new scoreboard diff --git a/include/qemu/rcu.h b/include/qemu/rcu.h index fea058a..020dbe4 100644 --- a/include/qemu/rcu.h +++ b/include/qemu/rcu.h @@ -17,8 +17,8 @@ * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * 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. */ diff --git a/include/qemu/rcu_queue.h b/include/qemu/rcu_queue.h index 4e6298d..bfd5900 100644 --- a/include/qemu/rcu_queue.h +++ b/include/qemu/rcu_queue.h @@ -17,8 +17,8 @@ * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * License along with this library; if not, see + * <https://www.gnu.org/licenses/>. * * Copyright (c) 2013 Mike D. Day, IBM Corporation. * diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h index c562690..be351d8 100644 --- a/include/qemu/sockets.h +++ b/include/qemu/sockets.h @@ -46,9 +46,6 @@ ssize_t qemu_send_full(int s, const void *buf, size_t count) G_GNUC_WARN_UNUSED_RESULT; int socket_set_cork(int fd, int v); int socket_set_nodelay(int fd); -void qemu_socket_set_block(int fd); -int qemu_socket_try_set_nonblock(int fd); -void qemu_socket_set_nonblock(int fd); int socket_set_fast_reuse(int fd); #ifdef WIN32 diff --git a/include/qemu/target-info-impl.h b/include/qemu/target-info-impl.h index 1b51cbc..e446585 100644 --- a/include/qemu/target-info-impl.h +++ b/include/qemu/target-info-impl.h @@ -9,17 +9,22 @@ #ifndef QEMU_TARGET_INFO_IMPL_H #define QEMU_TARGET_INFO_IMPL_H -#include "qemu/target-info.h" +#include "qapi/qapi-types-common.h" +#include "qapi/qapi-types-machine.h" typedef struct TargetInfo { /* runtime equivalent of TARGET_NAME definition */ const char *target_name; + /* related to TARGET_ARCH definition */ + SysEmuTarget target_arch; /* runtime equivalent of TARGET_LONG_BITS definition */ unsigned long_bits; /* runtime equivalent of CPU_RESOLVING_TYPE definition */ const char *cpu_type; /* QOM typename machines for this binary must implement */ const char *machine_typename; + /* related to TARGET_BIG_ENDIAN definition */ + EndianMode endianness; } TargetInfo; /** diff --git a/include/qemu/target-info-qapi.h b/include/qemu/target-info-qapi.h new file mode 100644 index 0000000..d5ce052 --- /dev/null +++ b/include/qemu/target-info-qapi.h @@ -0,0 +1,29 @@ +/* + * QEMU target info API (returning QAPI types) + * + * Copyright (c) Linaro + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef QEMU_TARGET_INFO_EXTRA_H +#define QEMU_TARGET_INFO_EXTRA_H + +#include "qapi/qapi-types-common.h" +#include "qapi/qapi-types-machine.h" + +/** + * target_arch: + * + * Returns: QAPI SysEmuTarget enum (e.g. SYS_EMU_TARGET_X86_64). + */ +SysEmuTarget target_arch(void); + +/** + * target_endian_mode: + * + * Returns: QAPI EndianMode enum (e.g. ENDIAN_MODE_LITTLE). + */ +EndianMode target_endian_mode(void); + +#endif diff --git a/include/qemu/target-info.h b/include/qemu/target-info.h index 850a295..6235962 100644 --- a/include/qemu/target-info.h +++ b/include/qemu/target-info.h @@ -1,5 +1,5 @@ /* - * QEMU target info API + * QEMU target info API (returning native types) * * Copyright (c) Linaro * @@ -38,4 +38,37 @@ const char *target_machine_typename(void); */ const char *target_cpu_type(void); +/** + * target_big_endian: + * + * Returns: %true if the (default) endianness of the target is big endian, + * %false otherwise. + * + * Common code should normally never need to know about the endianness of + * the target, so please do *not* use this function unless you know very + * well what you are doing! + */ +bool target_big_endian(void); + +/** + * target_base_arm: + * + * Returns whether the target architecture is ARM or Aarch64. + */ +bool target_base_arm(void); + +/** + * target_arm: + * + * Returns whether the target architecture is ARM (32-bit, not Aarch64). + */ +bool target_arm(void); + +/** + * target_aarch64: + * + * Returns whether the target architecture is Aarch64. + */ +bool target_aarch64(void); + #endif diff --git a/include/qemu/thread-posix.h b/include/qemu/thread-posix.h index 5f2f3d1..758808b 100644 --- a/include/qemu/thread-posix.h +++ b/include/qemu/thread-posix.h @@ -32,15 +32,6 @@ struct QemuSemaphore { unsigned int count; }; -struct QemuEvent { -#ifndef __linux__ - pthread_mutex_t lock; - pthread_cond_t cond; -#endif - unsigned value; - bool initialized; -}; - struct QemuThread { pthread_t thread; }; diff --git a/include/qemu/thread-win32.h b/include/qemu/thread-win32.h index d95af44..da9e732 100644 --- a/include/qemu/thread-win32.h +++ b/include/qemu/thread-win32.h @@ -28,12 +28,6 @@ struct QemuSemaphore { bool initialized; }; -struct QemuEvent { - int value; - HANDLE event; - bool initialized; -}; - typedef struct QemuThreadData QemuThreadData; struct QemuThread { QemuThreadData *data; diff --git a/include/qemu/thread.h b/include/qemu/thread.h index 6f800aa..f0302ed 100644 --- a/include/qemu/thread.h +++ b/include/qemu/thread.h @@ -3,13 +3,32 @@ #include "qemu/processor.h" #include "qemu/atomic.h" +#include "qemu/futex.h" typedef struct QemuCond QemuCond; typedef struct QemuSemaphore QemuSemaphore; -typedef struct QemuEvent QemuEvent; typedef struct QemuLockCnt QemuLockCnt; typedef struct QemuThread QemuThread; +/* + * QemuEvent + * ========= + * + * QemuEvent is an implementation of Win32 manual-reset event object. + * For details, refer to: + * https://learn.microsoft.com/en-us/windows/win32/sync/using-event-objects + * + * QemuEvent is more lightweight than QemuSemaphore when HAVE_FUTEX is defined. + */ +typedef struct QemuEvent { +#ifndef HAVE_FUTEX + pthread_mutex_t lock; + pthread_cond_t cond; +#endif + unsigned value; + bool initialized; +} QemuEvent; + #ifdef _WIN32 #include "qemu/thread-win32.h" #else diff --git a/include/qemu/timer.h b/include/qemu/timer.h index abd2204..8b561cd 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -699,7 +699,7 @@ void timer_mod_anticipate(QEMUTimer *ts, int64_t expire_time); * * Returns: true if the timer is pending */ -bool timer_pending(QEMUTimer *ts); +bool timer_pending(const QEMUTimer *ts); /** * timer_expired: @@ -710,7 +710,7 @@ bool timer_pending(QEMUTimer *ts); * * Returns: true if the timer has expired */ -bool timer_expired(QEMUTimer *timer_head, int64_t current_time); +bool timer_expired(const QEMUTimer *timer_head, int64_t current_time); /** * timer_expire_time_ns: @@ -720,7 +720,7 @@ bool timer_expired(QEMUTimer *timer_head, int64_t current_time); * * Returns: the expiry time in nanoseconds */ -uint64_t timer_expire_time_ns(QEMUTimer *ts); +uint64_t timer_expire_time_ns(const QEMUTimer *ts); /** * timer_get: @@ -786,11 +786,12 @@ static inline int64_t qemu_soonest_timeout(int64_t timeout1, int64_t timeout2) } /** - * initclocks: + * qemu_init_clocks: + * @notify_cb: optional call-back for timer expiry * * Initialise the clock & timer infrastructure */ -void init_clocks(QEMUTimerListNotifyCB *notify_cb); +void qemu_init_clocks(QEMUTimerListNotifyCB *notify_cb); static inline int64_t get_max_clock_jump(void) { @@ -850,12 +851,11 @@ static inline int64_t get_clock(void) /*******************************************/ /* host CPU ticks (if available) */ -#if defined(_ARCH_PPC) +#if defined(_ARCH_PPC64) static inline int64_t cpu_get_host_ticks(void) { int64_t retval; -#ifdef _ARCH_PPC64 /* This reads timebase in one 64bit go and includes Cell workaround from: http://ozlabs.org/pipermail/linuxppc-dev/2006-October/027052.html */ @@ -863,16 +863,6 @@ static inline int64_t cpu_get_host_ticks(void) "cmpwi %0,0\n\t" "beq- $-8" : "=r" (retval)); -#else - /* http://ozlabs.org/pipermail/linuxppc-dev/1999-October/003889.html */ - unsigned long junk; - __asm__ __volatile__ ("mfspr %1,269\n\t" /* mftbu */ - "mfspr %L0,268\n\t" /* mftb */ - "mfspr %0,269\n\t" /* mftbu */ - "cmpw %0,%1\n\t" - "bne $-16" - : "=r" (retval), "=r" (junk)); -#endif return retval; } diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h index 507f081..4a94af9 100644 --- a/include/qemu/typedefs.h +++ b/include/qemu/typedefs.h @@ -109,7 +109,7 @@ typedef struct QString QString; typedef struct RAMBlock RAMBlock; typedef struct Range Range; typedef struct ReservedRegion ReservedRegion; -typedef struct SaveLiveCompletePrecopyThreadData SaveLiveCompletePrecopyThreadData; +typedef struct SaveCompletePrecopyThreadData SaveCompletePrecopyThreadData; typedef struct SHPCDevice SHPCDevice; typedef struct SSIBus SSIBus; typedef struct TCGCPUOps TCGCPUOps; @@ -135,7 +135,7 @@ typedef struct IRQState *qemu_irq; typedef void (*qemu_irq_handler)(void *opaque, int n, int level); typedef bool (*MigrationLoadThread)(void *opaque, bool *should_quit, Error **errp); -typedef bool (*SaveLiveCompletePrecopyThreadHandler)(SaveLiveCompletePrecopyThreadData *d, - Error **errp); +typedef bool (*SaveCompletePrecopyThreadHandler)(SaveCompletePrecopyThreadData *d, + Error **errp); #endif /* QEMU_TYPEDEFS_H */ diff --git a/include/qemu/xattr.h b/include/qemu/xattr.h index b08a934..224ba12 100644 --- a/include/qemu/xattr.h +++ b/include/qemu/xattr.h @@ -26,7 +26,11 @@ # define ENOATTR ENODATA # endif # ifndef CONFIG_WIN32 -# include <sys/xattr.h> +# ifdef CONFIG_FREEBSD +# include <sys/extattr.h> +# else +# include <sys/xattr.h> +# endif # endif #endif diff --git a/include/qobject/qdict.h b/include/qobject/qdict.h index 903e6e5..861996f 100644 --- a/include/qobject/qdict.h +++ b/include/qobject/qdict.h @@ -57,6 +57,7 @@ void qdict_put_str(QDict *qdict, const char *key, const char *value); double qdict_get_double(const QDict *qdict, const char *key); int64_t qdict_get_int(const QDict *qdict, const char *key); +uint64_t qdict_get_uint(const QDict *qdict, const char *key); bool qdict_get_bool(const QDict *qdict, const char *key); QList *qdict_get_qlist(const QDict *qdict, const char *key); QDict *qdict_get_qdict(const QDict *qdict, const char *key); diff --git a/include/qobject/qobject.h b/include/qobject/qobject.h index a6244d0..02f4c6a 100644 --- a/include/qobject/qobject.h +++ b/include/qobject/qobject.h @@ -32,6 +32,7 @@ #ifndef QOBJECT_H #define QOBJECT_H +#include "qemu/atomic.h" #include "qapi/qapi-builtin-types.h" /* Not for use outside include/qobject/ */ @@ -73,7 +74,7 @@ QEMU_BUILD_BUG_MSG(QTYPE__MAX != 7, static inline void qobject_ref_impl(QObject *obj) { if (obj) { - obj->base.refcnt++; + qatomic_inc(&obj->base.refcnt); } } @@ -95,7 +96,7 @@ void qobject_destroy(QObject *obj); static inline void qobject_unref_impl(QObject *obj) { assert(!obj || obj->base.refcnt); - if (obj && --obj->base.refcnt == 0) { + if (obj && qatomic_fetch_dec(&obj->base.refcnt) == 1) { qobject_destroy(obj); } } diff --git a/include/semihosting/common-semi.h b/include/semihosting/common-semi.h index 0a91db7..aa511a4 100644 --- a/include/semihosting/common-semi.h +++ b/include/semihosting/common-semi.h @@ -35,5 +35,11 @@ #define COMMON_SEMI_H void do_common_semihosting(CPUState *cs); +uint64_t common_semi_arg(CPUState *cs, int argno); +void common_semi_set_ret(CPUState *cs, uint64_t ret); +bool is_64bit_semihosting(CPUArchState *env); +bool common_semi_sys_exit_is_extended(CPUState *cs); +uint64_t common_semi_stack_bottom(CPUState *cs); +bool common_semi_has_synccache(CPUArchState *env); #endif /* COMMON_SEMI_H */ diff --git a/include/semihosting/guestfd.h b/include/semihosting/guestfd.h index 3d426fe..a7ea104 100644 --- a/include/semihosting/guestfd.h +++ b/include/semihosting/guestfd.h @@ -35,13 +35,6 @@ typedef struct GuestFD { }; } GuestFD; -/* - * For ARM semihosting, we have a separate structure for routing - * data for the console which is outside the guest fd address space. - */ -extern GuestFD console_in_gf; -extern GuestFD console_out_gf; - /** * alloc_guestfd: * diff --git a/include/semihosting/semihost.h b/include/semihosting/semihost.h index b03e637..231dc89 100644 --- a/include/semihosting/semihost.h +++ b/include/semihosting/semihost.h @@ -33,6 +33,8 @@ typedef enum SemihostingTarget { * Return true if guest code is allowed to make semihosting calls. */ bool semihosting_enabled(bool is_user); +bool semihosting_arm_compatible(void); +void semihosting_arm_compatible_init(void); SemihostingTarget semihosting_get_target(void); const char *semihosting_get_arg(int i); diff --git a/include/semihosting/syscalls.h b/include/semihosting/syscalls.h index 6627c45..03aa45b 100644 --- a/include/semihosting/syscalls.h +++ b/include/semihosting/syscalls.h @@ -9,7 +9,7 @@ #ifndef SEMIHOSTING_SYSCALLS_H #define SEMIHOSTING_SYSCALLS_H -#include "exec/cpu-defs.h" +#include "exec/vaddr.h" #include "gdbstub/syscalls.h" /* @@ -24,23 +24,23 @@ typedef struct GuestFD GuestFD; void semihost_sys_open(CPUState *cs, gdb_syscall_complete_cb complete, - target_ulong fname, target_ulong fname_len, + vaddr fname, uint64_t fname_len, int gdb_flags, int mode); void semihost_sys_close(CPUState *cs, gdb_syscall_complete_cb complete, int fd); void semihost_sys_read(CPUState *cs, gdb_syscall_complete_cb complete, - int fd, target_ulong buf, target_ulong len); + int fd, vaddr buf, uint64_t len); void semihost_sys_read_gf(CPUState *cs, gdb_syscall_complete_cb complete, - GuestFD *gf, target_ulong buf, target_ulong len); + GuestFD *gf, vaddr buf, uint64_t len); void semihost_sys_write(CPUState *cs, gdb_syscall_complete_cb complete, - int fd, target_ulong buf, target_ulong len); + int fd, vaddr buf, uint64_t len); void semihost_sys_write_gf(CPUState *cs, gdb_syscall_complete_cb complete, - GuestFD *gf, target_ulong buf, target_ulong len); + GuestFD *gf, vaddr buf, uint64_t len); void semihost_sys_lseek(CPUState *cs, gdb_syscall_complete_cb complete, int fd, int64_t off, int gdb_whence); @@ -50,27 +50,27 @@ void semihost_sys_isatty(CPUState *cs, gdb_syscall_complete_cb complete, void semihost_sys_flen(CPUState *cs, gdb_syscall_complete_cb fstat_cb, gdb_syscall_complete_cb flen_cb, - int fd, target_ulong fstat_addr); + int fd, vaddr fstat_addr); void semihost_sys_fstat(CPUState *cs, gdb_syscall_complete_cb complete, - int fd, target_ulong addr); + int fd, vaddr addr); void semihost_sys_stat(CPUState *cs, gdb_syscall_complete_cb complete, - target_ulong fname, target_ulong fname_len, - target_ulong addr); + vaddr fname, uint64_t fname_len, + vaddr addr); void semihost_sys_remove(CPUState *cs, gdb_syscall_complete_cb complete, - target_ulong fname, target_ulong fname_len); + vaddr fname, uint64_t fname_len); void semihost_sys_rename(CPUState *cs, gdb_syscall_complete_cb complete, - target_ulong oname, target_ulong oname_len, - target_ulong nname, target_ulong nname_len); + vaddr oname, uint64_t oname_len, + vaddr nname, uint64_t nname_len); void semihost_sys_system(CPUState *cs, gdb_syscall_complete_cb complete, - target_ulong cmd, target_ulong cmd_len); + vaddr cmd, uint64_t cmd_len); void semihost_sys_gettimeofday(CPUState *cs, gdb_syscall_complete_cb complete, - target_ulong tv_addr, target_ulong tz_addr); + vaddr tv_addr, vaddr tz_addr); void semihost_sys_poll_one(CPUState *cs, gdb_syscall_complete_cb complete, int fd, GIOCondition cond, int timeout); diff --git a/include/semihosting/uaccess.h b/include/semihosting/uaccess.h index 6bc90b1..2093a49 100644 --- a/include/semihosting/uaccess.h +++ b/include/semihosting/uaccess.h @@ -15,9 +15,9 @@ #endif #include "exec/cpu-common.h" -#include "exec/cpu-defs.h" #include "exec/tswap.h" #include "exec/page-protection.h" +#include "exec/vaddr.h" /** * get_user_u64: @@ -89,8 +89,8 @@ * * The returned pointer should be freed using uaccess_unlock_user(). */ -void *uaccess_lock_user(CPUArchState *env, target_ulong addr, - target_ulong len, bool copy); +void *uaccess_lock_user(CPUArchState *env, vaddr addr, + size_t len, bool copy); /** * lock_user: * @@ -103,7 +103,7 @@ void *uaccess_lock_user(CPUArchState *env, target_ulong addr, * * The returned string should be freed using uaccess_unlock_user(). */ -char *uaccess_lock_user_string(CPUArchState *env, target_ulong addr); +char *uaccess_lock_user_string(CPUArchState *env, vaddr addr); /** * uaccess_lock_user_string: * @@ -112,10 +112,10 @@ char *uaccess_lock_user_string(CPUArchState *env, target_ulong addr); #define lock_user_string(p) uaccess_lock_user_string(env, p) void uaccess_unlock_user(CPUArchState *env, void *p, - target_ulong addr, target_ulong len); + vaddr addr, size_t len); #define unlock_user(s, args, len) uaccess_unlock_user(env, s, args, len) -ssize_t uaccess_strlen_user(CPUArchState *env, target_ulong addr); +ssize_t uaccess_strlen_user(CPUArchState *env, vaddr addr); #define target_strlen(p) uaccess_strlen_user(env, p) #endif /* SEMIHOSTING_SOFTMMU_UACCESS_H */ diff --git a/include/standard-headers/asm-x86/setup_data.h b/include/standard-headers/asm-x86/setup_data.h index a483d72..2e446c1d 100644 --- a/include/standard-headers/asm-x86/setup_data.h +++ b/include/standard-headers/asm-x86/setup_data.h @@ -13,7 +13,8 @@ #define SETUP_CC_BLOB 7 #define SETUP_IMA 8 #define SETUP_RNG_SEED 9 -#define SETUP_ENUM_MAX SETUP_RNG_SEED +#define SETUP_KEXEC_KHO 10 +#define SETUP_ENUM_MAX SETUP_KEXEC_KHO #define SETUP_INDIRECT (1<<31) #define SETUP_TYPE_MAX (SETUP_ENUM_MAX | SETUP_INDIRECT) @@ -78,6 +79,16 @@ struct ima_setup_data { uint64_t size; } QEMU_PACKED; +/* + * Locations of kexec handover metadata + */ +struct kho_data { + uint64_t fdt_addr; + uint64_t fdt_size; + uint64_t scratch_addr; + uint64_t scratch_size; +} QEMU_PACKED; + #endif /* __ASSEMBLER__ */ #endif /* _ASM_X86_SETUP_DATA_H */ diff --git a/include/standard-headers/drm/drm_fourcc.h b/include/standard-headers/drm/drm_fourcc.h index a8b759d..cef077d 100644 --- a/include/standard-headers/drm/drm_fourcc.h +++ b/include/standard-headers/drm/drm_fourcc.h @@ -209,6 +209,10 @@ extern "C" { #define DRM_FORMAT_RGBA1010102 fourcc_code('R', 'A', '3', '0') /* [31:0] R:G:B:A 10:10:10:2 little endian */ #define DRM_FORMAT_BGRA1010102 fourcc_code('B', 'A', '3', '0') /* [31:0] B:G:R:A 10:10:10:2 little endian */ +/* 48 bpp RGB */ +#define DRM_FORMAT_RGB161616 fourcc_code('R', 'G', '4', '8') /* [47:0] R:G:B 16:16:16 little endian */ +#define DRM_FORMAT_BGR161616 fourcc_code('B', 'G', '4', '8') /* [47:0] B:G:R 16:16:16 little endian */ + /* 64 bpp RGB */ #define DRM_FORMAT_XRGB16161616 fourcc_code('X', 'R', '4', '8') /* [63:0] x:R:G:B 16:16:16:16 little endian */ #define DRM_FORMAT_XBGR16161616 fourcc_code('X', 'B', '4', '8') /* [63:0] x:B:G:R 16:16:16:16 little endian */ @@ -217,7 +221,7 @@ extern "C" { #define DRM_FORMAT_ABGR16161616 fourcc_code('A', 'B', '4', '8') /* [63:0] A:B:G:R 16:16:16:16 little endian */ /* - * Floating point 64bpp RGB + * Half-Floating point - 16b/component * IEEE 754-2008 binary16 half-precision float * [15:0] sign:exponent:mantissa 1:5:10 */ @@ -227,6 +231,20 @@ extern "C" { #define DRM_FORMAT_ARGB16161616F fourcc_code('A', 'R', '4', 'H') /* [63:0] A:R:G:B 16:16:16:16 little endian */ #define DRM_FORMAT_ABGR16161616F fourcc_code('A', 'B', '4', 'H') /* [63:0] A:B:G:R 16:16:16:16 little endian */ +#define DRM_FORMAT_R16F fourcc_code('R', ' ', ' ', 'H') /* [15:0] R 16 little endian */ +#define DRM_FORMAT_GR1616F fourcc_code('G', 'R', ' ', 'H') /* [31:0] G:R 16:16 little endian */ +#define DRM_FORMAT_BGR161616F fourcc_code('B', 'G', 'R', 'H') /* [47:0] B:G:R 16:16:16 little endian */ + +/* + * Floating point - 32b/component + * IEEE 754-2008 binary32 float + * [31:0] sign:exponent:mantissa 1:8:23 + */ +#define DRM_FORMAT_R32F fourcc_code('R', ' ', ' ', 'F') /* [31:0] R 32 little endian */ +#define DRM_FORMAT_GR3232F fourcc_code('G', 'R', ' ', 'F') /* [63:0] R:G 32:32 little endian */ +#define DRM_FORMAT_BGR323232F fourcc_code('B', 'G', 'R', 'F') /* [95:0] R:G:B 32:32:32 little endian */ +#define DRM_FORMAT_ABGR32323232F fourcc_code('A', 'B', '8', 'F') /* [127:0] R:G:B:A 32:32:32:32 little endian */ + /* * RGBA format with 10-bit components packed in 64-bit per pixel, with 6 bits * of unused padding per component: @@ -377,6 +395,42 @@ extern "C" { #define DRM_FORMAT_Q401 fourcc_code('Q', '4', '0', '1') /* + * 3 plane YCbCr LSB aligned + * In order to use these formats in a similar fashion to MSB aligned ones + * implementation can multiply the values by 2^6=64. For that reason the padding + * must only contain zeros. + * index 0 = Y plane, [15:0] z:Y [6:10] little endian + * index 1 = Cr plane, [15:0] z:Cr [6:10] little endian + * index 2 = Cb plane, [15:0] z:Cb [6:10] little endian + */ +#define DRM_FORMAT_S010 fourcc_code('S', '0', '1', '0') /* 2x2 subsampled Cb (1) and Cr (2) planes 10 bits per channel */ +#define DRM_FORMAT_S210 fourcc_code('S', '2', '1', '0') /* 2x1 subsampled Cb (1) and Cr (2) planes 10 bits per channel */ +#define DRM_FORMAT_S410 fourcc_code('S', '4', '1', '0') /* non-subsampled Cb (1) and Cr (2) planes 10 bits per channel */ + +/* + * 3 plane YCbCr LSB aligned + * In order to use these formats in a similar fashion to MSB aligned ones + * implementation can multiply the values by 2^4=16. For that reason the padding + * must only contain zeros. + * index 0 = Y plane, [15:0] z:Y [4:12] little endian + * index 1 = Cr plane, [15:0] z:Cr [4:12] little endian + * index 2 = Cb plane, [15:0] z:Cb [4:12] little endian + */ +#define DRM_FORMAT_S012 fourcc_code('S', '0', '1', '2') /* 2x2 subsampled Cb (1) and Cr (2) planes 12 bits per channel */ +#define DRM_FORMAT_S212 fourcc_code('S', '2', '1', '2') /* 2x1 subsampled Cb (1) and Cr (2) planes 12 bits per channel */ +#define DRM_FORMAT_S412 fourcc_code('S', '4', '1', '2') /* non-subsampled Cb (1) and Cr (2) planes 12 bits per channel */ + +/* + * 3 plane YCbCr + * index 0 = Y plane, [15:0] Y little endian + * index 1 = Cr plane, [15:0] Cr little endian + * index 2 = Cb plane, [15:0] Cb little endian + */ +#define DRM_FORMAT_S016 fourcc_code('S', '0', '1', '6') /* 2x2 subsampled Cb (1) and Cr (2) planes 16 bits per channel */ +#define DRM_FORMAT_S216 fourcc_code('S', '2', '1', '6') /* 2x1 subsampled Cb (1) and Cr (2) planes 16 bits per channel */ +#define DRM_FORMAT_S416 fourcc_code('S', '4', '1', '6') /* non-subsampled Cb (1) and Cr (2) planes 16 bits per channel */ + +/* * 3 plane YCbCr * index 0: Y plane, [7:0] Y * index 1: Cb plane, [7:0] Cb @@ -421,6 +475,7 @@ extern "C" { #define DRM_FORMAT_MOD_VENDOR_ALLWINNER 0x09 #define DRM_FORMAT_MOD_VENDOR_AMLOGIC 0x0a #define DRM_FORMAT_MOD_VENDOR_MTK 0x0b +#define DRM_FORMAT_MOD_VENDOR_APPLE 0x0c /* add more to the end as needed */ @@ -1494,6 +1549,50 @@ drm_fourcc_canonicalize_nvidia_format_mod(uint64_t modifier) #define DRM_FORMAT_MOD_MTK_16L_32S_TILE DRM_FORMAT_MOD_MTK(MTK_FMT_MOD_TILE_16L32S) /* + * Apple GPU-tiled layouts. + * + * Apple GPUs support nonlinear tilings with optional lossless compression. + * + * GPU-tiled images are divided into 16KiB tiles: + * + * Bytes per pixel Tile size + * --------------- --------- + * 1 128x128 + * 2 128x64 + * 4 64x64 + * 8 64x32 + * 16 32x32 + * + * Tiles are raster-order. Pixels within a tile are interleaved (Morton order). + * + * Compressed images pad the body to 128-bytes and are immediately followed by a + * metadata section. The metadata section rounds the image dimensions to + * powers-of-two and contains 8 bytes for each 16x16 compression subtile. + * Subtiles are interleaved (Morton order). + * + * All images are 128-byte aligned. + * + * These layouts fundamentally do not have meaningful strides. No matter how we + * specify strides for these layouts, userspace unaware of Apple image layouts + * will be unable to use correctly the specified stride for any purpose. + * Userspace aware of the image layouts do not use strides. The most "correct" + * convention would be setting the image stride to 0. Unfortunately, some + * software assumes the stride is at least (width * bytes per pixel). We + * therefore require that stride equals (width * bytes per pixel). Since the + * stride is arbitrary here, we pick the simplest convention. + * + * Although containing two sections, compressed image layouts are treated in + * software as a single plane. This is modelled after AFBC, a similar + * scheme. Attempting to separate the sections to be "explicit" in DRM would + * only generate more confusion, as software does not treat the image this way. + * + * For detailed information on the hardware image layouts, see + * https://docs.mesa3d.org/drivers/asahi.html#image-layouts + */ +#define DRM_FORMAT_MOD_APPLE_GPU_TILED fourcc_mod_code(APPLE, 1) +#define DRM_FORMAT_MOD_APPLE_GPU_TILED_COMPRESSED fourcc_mod_code(APPLE, 2) + +/* * AMD modifiers * * Memory layout: diff --git a/include/standard-headers/linux/ethtool.h b/include/standard-headers/linux/ethtool.h index 5d1ad5f..dc24512 100644 --- a/include/standard-headers/linux/ethtool.h +++ b/include/standard-headers/linux/ethtool.h @@ -2295,71 +2295,75 @@ static inline int ethtool_validate_duplex(uint8_t duplex) #define RXH_XFRM_SYM_OR_XOR (1 << 1) #define RXH_XFRM_NO_CHANGE 0xff -/* L2-L4 network traffic flow types */ -#define TCP_V4_FLOW 0x01 /* hash or spec (tcp_ip4_spec) */ -#define UDP_V4_FLOW 0x02 /* hash or spec (udp_ip4_spec) */ -#define SCTP_V4_FLOW 0x03 /* hash or spec (sctp_ip4_spec) */ -#define AH_ESP_V4_FLOW 0x04 /* hash only */ -#define TCP_V6_FLOW 0x05 /* hash or spec (tcp_ip6_spec; nfc only) */ -#define UDP_V6_FLOW 0x06 /* hash or spec (udp_ip6_spec; nfc only) */ -#define SCTP_V6_FLOW 0x07 /* hash or spec (sctp_ip6_spec; nfc only) */ -#define AH_ESP_V6_FLOW 0x08 /* hash only */ -#define AH_V4_FLOW 0x09 /* hash or spec (ah_ip4_spec) */ -#define ESP_V4_FLOW 0x0a /* hash or spec (esp_ip4_spec) */ -#define AH_V6_FLOW 0x0b /* hash or spec (ah_ip6_spec; nfc only) */ -#define ESP_V6_FLOW 0x0c /* hash or spec (esp_ip6_spec; nfc only) */ -#define IPV4_USER_FLOW 0x0d /* spec only (usr_ip4_spec) */ -#define IP_USER_FLOW IPV4_USER_FLOW -#define IPV6_USER_FLOW 0x0e /* spec only (usr_ip6_spec; nfc only) */ -#define IPV4_FLOW 0x10 /* hash only */ -#define IPV6_FLOW 0x11 /* hash only */ -#define ETHER_FLOW 0x12 /* spec only (ether_spec) */ - -/* Used for GTP-U IPv4 and IPv6. - * The format of GTP packets only includes - * elements such as TEID and GTP version. - * It is primarily intended for data communication of the UE. - */ -#define GTPU_V4_FLOW 0x13 /* hash only */ -#define GTPU_V6_FLOW 0x14 /* hash only */ - -/* Use for GTP-C IPv4 and v6. - * The format of these GTP packets does not include TEID. - * Primarily expected to be used for communication - * to create sessions for UE data communication, - * commonly referred to as CSR (Create Session Request). - */ -#define GTPC_V4_FLOW 0x15 /* hash only */ -#define GTPC_V6_FLOW 0x16 /* hash only */ - -/* Use for GTP-C IPv4 and v6. - * Unlike GTPC_V4_FLOW, the format of these GTP packets includes TEID. - * After session creation, it becomes this packet. - * This is mainly used for requests to realize UE handover. - */ -#define GTPC_TEID_V4_FLOW 0x17 /* hash only */ -#define GTPC_TEID_V6_FLOW 0x18 /* hash only */ - -/* Use for GTP-U and extended headers for the PSC (PDU Session Container). - * The format of these GTP packets includes TEID and QFI. - * In 5G communication using UPF (User Plane Function), - * data communication with this extended header is performed. - */ -#define GTPU_EH_V4_FLOW 0x19 /* hash only */ -#define GTPU_EH_V6_FLOW 0x1a /* hash only */ - -/* Use for GTP-U IPv4 and v6 PSC (PDU Session Container) extended headers. - * This differs from GTPU_EH_V(4|6)_FLOW in that it is distinguished by - * UL/DL included in the PSC. - * There are differences in the data included based on Downlink/Uplink, - * and can be used to distinguish packets. - * The functions described so far are useful when you want to - * handle communication from the mobile network in UPF, PGW, etc. - */ -#define GTPU_UL_V4_FLOW 0x1b /* hash only */ -#define GTPU_UL_V6_FLOW 0x1c /* hash only */ -#define GTPU_DL_V4_FLOW 0x1d /* hash only */ -#define GTPU_DL_V6_FLOW 0x1e /* hash only */ +enum { + /* L2-L4 network traffic flow types */ + TCP_V4_FLOW = 0x01, /* hash or spec (tcp_ip4_spec) */ + UDP_V4_FLOW = 0x02, /* hash or spec (udp_ip4_spec) */ + SCTP_V4_FLOW = 0x03, /* hash or spec (sctp_ip4_spec) */ + AH_ESP_V4_FLOW = 0x04, /* hash only */ + TCP_V6_FLOW = 0x05, /* hash or spec (tcp_ip6_spec; nfc only) */ + UDP_V6_FLOW = 0x06, /* hash or spec (udp_ip6_spec; nfc only) */ + SCTP_V6_FLOW = 0x07, /* hash or spec (sctp_ip6_spec; nfc only) */ + AH_ESP_V6_FLOW = 0x08, /* hash only */ + AH_V4_FLOW = 0x09, /* hash or spec (ah_ip4_spec) */ + ESP_V4_FLOW = 0x0a, /* hash or spec (esp_ip4_spec) */ + AH_V6_FLOW = 0x0b, /* hash or spec (ah_ip6_spec; nfc only) */ + ESP_V6_FLOW = 0x0c, /* hash or spec (esp_ip6_spec; nfc only) */ + IPV4_USER_FLOW = 0x0d, /* spec only (usr_ip4_spec) */ + IP_USER_FLOW = IPV4_USER_FLOW, + IPV6_USER_FLOW = 0x0e, /* spec only (usr_ip6_spec; nfc only) */ + IPV4_FLOW = 0x10, /* hash only */ + IPV6_FLOW = 0x11, /* hash only */ + ETHER_FLOW = 0x12, /* hash or spec (ether_spec) */ + + /* Used for GTP-U IPv4 and IPv6. + * The format of GTP packets only includes + * elements such as TEID and GTP version. + * It is primarily intended for data communication of the UE. + */ + GTPU_V4_FLOW = 0x13, /* hash only */ + GTPU_V6_FLOW = 0x14, /* hash only */ + + /* Use for GTP-C IPv4 and v6. + * The format of these GTP packets does not include TEID. + * Primarily expected to be used for communication + * to create sessions for UE data communication, + * commonly referred to as CSR (Create Session Request). + */ + GTPC_V4_FLOW = 0x15, /* hash only */ + GTPC_V6_FLOW = 0x16, /* hash only */ + + /* Use for GTP-C IPv4 and v6. + * Unlike GTPC_V4_FLOW, the format of these GTP packets includes TEID. + * After session creation, it becomes this packet. + * This is mainly used for requests to realize UE handover. + */ + GTPC_TEID_V4_FLOW = 0x17, /* hash only */ + GTPC_TEID_V6_FLOW = 0x18, /* hash only */ + + /* Use for GTP-U and extended headers for the PSC (PDU Session Container). + * The format of these GTP packets includes TEID and QFI. + * In 5G communication using UPF (User Plane Function), + * data communication with this extended header is performed. + */ + GTPU_EH_V4_FLOW = 0x19, /* hash only */ + GTPU_EH_V6_FLOW = 0x1a, /* hash only */ + + /* Use for GTP-U IPv4 and v6 PSC (PDU Session Container) extended headers. + * This differs from GTPU_EH_V(4|6)_FLOW in that it is distinguished by + * UL/DL included in the PSC. + * There are differences in the data included based on Downlink/Uplink, + * and can be used to distinguish packets. + * The functions described so far are useful when you want to + * handle communication from the mobile network in UPF, PGW, etc. + */ + GTPU_UL_V4_FLOW = 0x1b, /* hash only */ + GTPU_UL_V6_FLOW = 0x1c, /* hash only */ + GTPU_DL_V4_FLOW = 0x1d, /* hash only */ + GTPU_DL_V6_FLOW = 0x1e, /* hash only */ + + __FLOW_TYPE_COUNT, +}; /* Flag to enable additional fields in struct ethtool_rx_flow_spec */ #define FLOW_EXT 0x80000000 @@ -2367,7 +2371,7 @@ static inline int ethtool_validate_duplex(uint8_t duplex) /* Flag to enable RSS spreading of traffic matching rule (nfc only) */ #define FLOW_RSS 0x20000000 -/* L3-L4 network traffic flow hash options */ +/* L2-L4 network traffic flow hash options */ #define RXH_L2DA (1 << 1) #define RXH_VLAN (1 << 2) #define RXH_L3_PROTO (1 << 3) @@ -2376,6 +2380,7 @@ static inline int ethtool_validate_duplex(uint8_t duplex) #define RXH_L4_B_0_1 (1 << 6) /* src port in case of TCP/UDP/SCTP */ #define RXH_L4_B_2_3 (1 << 7) /* dst port in case of TCP/UDP/SCTP */ #define RXH_GTP_TEID (1 << 8) /* teid in case of GTP */ +#define RXH_IP6_FL (1 << 9) /* IPv6 flow label */ #define RXH_DISCARD (1 << 31) #define RX_CLS_FLOW_DISC 0xffffffffffffffffULL diff --git a/include/standard-headers/linux/fuse.h b/include/standard-headers/linux/fuse.h index a2b5815..abf3a78 100644 --- a/include/standard-headers/linux/fuse.h +++ b/include/standard-headers/linux/fuse.h @@ -232,6 +232,14 @@ * * 7.43 * - add FUSE_REQUEST_TIMEOUT + * + * 7.44 + * - add FUSE_NOTIFY_INC_EPOCH + * + * 7.45 + * - add FUSE_COPY_FILE_RANGE_64 + * - add struct fuse_copy_file_range_out + * - add FUSE_NOTIFY_PRUNE */ #ifndef _LINUX_FUSE_H @@ -263,7 +271,7 @@ #define FUSE_KERNEL_VERSION 7 /** Minor version number of this interface */ -#define FUSE_KERNEL_MINOR_VERSION 43 +#define FUSE_KERNEL_MINOR_VERSION 45 /** The node ID of the root inode */ #define FUSE_ROOT_ID 1 @@ -650,6 +658,7 @@ enum fuse_opcode { FUSE_SYNCFS = 50, FUSE_TMPFILE = 51, FUSE_STATX = 52, + FUSE_COPY_FILE_RANGE_64 = 53, /* CUSE specific operations */ CUSE_INIT = 4096, @@ -667,7 +676,8 @@ enum fuse_notify_code { FUSE_NOTIFY_RETRIEVE = 5, FUSE_NOTIFY_DELETE = 6, FUSE_NOTIFY_RESEND = 7, - FUSE_NOTIFY_CODE_MAX, + FUSE_NOTIFY_INC_EPOCH = 8, + FUSE_NOTIFY_PRUNE = 9, }; /* The read buffer is required to be at least 8k, but may be much larger */ @@ -1106,6 +1116,12 @@ struct fuse_notify_retrieve_in { uint64_t dummy4; }; +struct fuse_notify_prune_out { + uint32_t count; + uint32_t padding; + uint64_t spare; +}; + struct fuse_backing_map { int32_t fd; uint32_t flags; @@ -1118,6 +1134,7 @@ struct fuse_backing_map { #define FUSE_DEV_IOC_BACKING_OPEN _IOW(FUSE_DEV_IOC_MAGIC, 1, \ struct fuse_backing_map) #define FUSE_DEV_IOC_BACKING_CLOSE _IOW(FUSE_DEV_IOC_MAGIC, 2, uint32_t) +#define FUSE_DEV_IOC_SYNC_INIT _IO(FUSE_DEV_IOC_MAGIC, 3) struct fuse_lseek_in { uint64_t fh; @@ -1140,6 +1157,11 @@ struct fuse_copy_file_range_in { uint64_t flags; }; +/* For FUSE_COPY_FILE_RANGE_64 */ +struct fuse_copy_file_range_out { + uint64_t bytes_copied; +}; + #define FUSE_SETUPMAPPING_FLAG_WRITE (1ull << 0) #define FUSE_SETUPMAPPING_FLAG_READ (1ull << 1) struct fuse_setupmapping_in { diff --git a/include/standard-headers/linux/input-event-codes.h b/include/standard-headers/linux/input-event-codes.h index 09ba0ad..c914ccd 100644 --- a/include/standard-headers/linux/input-event-codes.h +++ b/include/standard-headers/linux/input-event-codes.h @@ -27,6 +27,7 @@ #define INPUT_PROP_TOPBUTTONPAD 0x04 /* softbuttons at top of pad */ #define INPUT_PROP_POINTING_STICK 0x05 /* is a pointing stick */ #define INPUT_PROP_ACCELEROMETER 0x06 /* has accelerometer */ +#define INPUT_PROP_HAPTIC_TOUCHPAD 0x07 /* is a haptic touchpad */ #define INPUT_PROP_MAX 0x1f #define INPUT_PROP_CNT (INPUT_PROP_MAX + 1) @@ -601,6 +602,11 @@ #define BTN_DPAD_LEFT 0x222 #define BTN_DPAD_RIGHT 0x223 +#define BTN_GRIPL 0x224 +#define BTN_GRIPR 0x225 +#define BTN_GRIPL2 0x226 +#define BTN_GRIPR2 0x227 + #define KEY_ALS_TOGGLE 0x230 /* Ambient light sensor */ #define KEY_ROTATE_LOCK_TOGGLE 0x231 /* Display rotation lock */ #define KEY_REFRESH_RATE_TOGGLE 0x232 /* Display refresh rate toggle */ @@ -765,6 +771,9 @@ #define KEY_KBD_LCD_MENU4 0x2bb #define KEY_KBD_LCD_MENU5 0x2bc +/* Performance Boost key (Alienware)/G-Mode key (Dell) */ +#define KEY_PERFORMANCE 0x2bd + #define BTN_TRIGGER_HAPPY 0x2c0 #define BTN_TRIGGER_HAPPY1 0x2c0 #define BTN_TRIGGER_HAPPY2 0x2c1 @@ -925,7 +934,8 @@ #define SW_MUTE_DEVICE 0x0e /* set = device disabled */ #define SW_PEN_INSERTED 0x0f /* set = pen inserted */ #define SW_MACHINE_COVER 0x10 /* set = cover closed */ -#define SW_MAX_ 0x10 +#define SW_USB_INSERT 0x11 /* set = USB audio device connected */ +#define SW_MAX_ 0x11 #define SW_CNT (SW_MAX_+1) /* diff --git a/include/standard-headers/linux/input.h b/include/standard-headers/linux/input.h index 942ea6a..9aff211 100644 --- a/include/standard-headers/linux/input.h +++ b/include/standard-headers/linux/input.h @@ -272,6 +272,7 @@ struct input_mask { #define BUS_CEC 0x1E #define BUS_INTEL_ISHTP 0x1F #define BUS_AMD_SFH 0x20 +#define BUS_SDW 0x21 /* * MT_TOOL types @@ -426,6 +427,24 @@ struct ff_rumble_effect { }; /** + * struct ff_haptic_effect + * @hid_usage: hid_usage according to Haptics page (WAVEFORM_CLICK, etc.) + * @vendor_id: the waveform vendor ID if hid_usage is in the vendor-defined range + * @vendor_waveform_page: the vendor waveform page if hid_usage is in the vendor-defined range + * @intensity: strength of the effect as percentage + * @repeat_count: number of times to retrigger effect + * @retrigger_period: time before effect is retriggered (in ms) + */ +struct ff_haptic_effect { + uint16_t hid_usage; + uint16_t vendor_id; + uint8_t vendor_waveform_page; + uint16_t intensity; + uint16_t repeat_count; + uint16_t retrigger_period; +}; + +/** * struct ff_effect - defines force feedback effect * @type: type of the effect (FF_CONSTANT, FF_PERIODIC, FF_RAMP, FF_SPRING, * FF_FRICTION, FF_DAMPER, FF_RUMBLE, FF_INERTIA, or FF_CUSTOM) @@ -461,6 +480,7 @@ struct ff_effect { struct ff_periodic_effect periodic; struct ff_condition_effect condition[2]; /* One for each axis */ struct ff_rumble_effect rumble; + struct ff_haptic_effect haptic; } u; }; @@ -468,6 +488,7 @@ struct ff_effect { * Force feedback effect types */ +#define FF_HAPTIC 0x4f #define FF_RUMBLE 0x50 #define FF_PERIODIC 0x51 #define FF_CONSTANT 0x52 @@ -477,7 +498,7 @@ struct ff_effect { #define FF_INERTIA 0x56 #define FF_RAMP 0x57 -#define FF_EFFECT_MIN FF_RUMBLE +#define FF_EFFECT_MIN FF_HAPTIC #define FF_EFFECT_MAX FF_RAMP /* diff --git a/include/standard-headers/linux/pci_regs.h b/include/standard-headers/linux/pci_regs.h index ba32671..07e06aa 100644 --- a/include/standard-headers/linux/pci_regs.h +++ b/include/standard-headers/linux/pci_regs.h @@ -207,6 +207,9 @@ /* Capability lists */ +#define PCI_CAP_ID_MASK 0x00ff /* Capability ID mask */ +#define PCI_CAP_LIST_NEXT_MASK 0xff00 /* Next Capability Pointer mask */ + #define PCI_CAP_LIST_ID 0 /* Capability ID */ #define PCI_CAP_ID_PM 0x01 /* Power Management */ #define PCI_CAP_ID_AGP 0x02 /* Accelerated Graphics Port */ @@ -745,12 +748,14 @@ #define PCI_EXT_CAP_ID_L1SS 0x1E /* L1 PM Substates */ #define PCI_EXT_CAP_ID_PTM 0x1F /* Precision Time Measurement */ #define PCI_EXT_CAP_ID_DVSEC 0x23 /* Designated Vendor-Specific */ +#define PCI_EXT_CAP_ID_VF_REBAR 0x24 /* VF Resizable BAR */ #define PCI_EXT_CAP_ID_DLF 0x25 /* Data Link Feature */ #define PCI_EXT_CAP_ID_PL_16GT 0x26 /* Physical Layer 16.0 GT/s */ #define PCI_EXT_CAP_ID_NPEM 0x29 /* Native PCIe Enclosure Management */ #define PCI_EXT_CAP_ID_PL_32GT 0x2A /* Physical Layer 32.0 GT/s */ #define PCI_EXT_CAP_ID_DOE 0x2E /* Data Object Exchange */ -#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_DOE +#define PCI_EXT_CAP_ID_PL_64GT 0x31 /* Physical Layer 64.0 GT/s */ +#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_PL_64GT #define PCI_EXT_CAP_DSN_SIZEOF 12 #define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40 @@ -774,6 +779,12 @@ #define PCI_ERR_UNC_MCBTLP 0x00800000 /* MC blocked TLP */ #define PCI_ERR_UNC_ATOMEG 0x01000000 /* Atomic egress blocked */ #define PCI_ERR_UNC_TLPPRE 0x02000000 /* TLP prefix blocked */ +#define PCI_ERR_UNC_POISON_BLK 0x04000000 /* Poisoned TLP Egress Blocked */ +#define PCI_ERR_UNC_DMWR_BLK 0x08000000 /* DMWr Request Egress Blocked */ +#define PCI_ERR_UNC_IDE_CHECK 0x10000000 /* IDE Check Failed */ +#define PCI_ERR_UNC_MISR_IDE 0x20000000 /* Misrouted IDE TLP */ +#define PCI_ERR_UNC_PCRC_CHECK 0x40000000 /* PCRC Check Failed */ +#define PCI_ERR_UNC_XLAT_BLK 0x80000000 /* TLP Translation Egress Blocked */ #define PCI_ERR_UNCOR_MASK 0x08 /* Uncorrectable Error Mask */ /* Same bits as above */ #define PCI_ERR_UNCOR_SEVER 0x0c /* Uncorrectable Error Severity */ @@ -796,6 +807,7 @@ #define PCI_ERR_CAP_ECRC_CHKC 0x00000080 /* ECRC Check Capable */ #define PCI_ERR_CAP_ECRC_CHKE 0x00000100 /* ECRC Check Enable */ #define PCI_ERR_CAP_PREFIX_LOG_PRESENT 0x00000800 /* TLP Prefix Log Present */ +#define PCI_ERR_CAP_COMP_TIME_LOG 0x00001000 /* Completion Timeout Prefix/Header Log Capable */ #define PCI_ERR_CAP_TLP_LOG_FLIT 0x00040000 /* TLP was logged in Flit Mode */ #define PCI_ERR_CAP_TLP_LOG_SIZE 0x00f80000 /* Logged TLP Size (only in Flit mode) */ #define PCI_ERR_HEADER_LOG 0x1c /* Header Log Register (16 bytes) */ @@ -1140,16 +1152,33 @@ #define PCI_DVSEC_HEADER2 0x8 /* Designated Vendor-Specific Header2 */ #define PCI_DVSEC_HEADER2_ID(x) ((x) & 0xffff) +/* VF Resizable BARs, same layout as PCI_REBAR */ +#define PCI_VF_REBAR_CAP PCI_REBAR_CAP +#define PCI_VF_REBAR_CAP_SIZES PCI_REBAR_CAP_SIZES +#define PCI_VF_REBAR_CTRL PCI_REBAR_CTRL +#define PCI_VF_REBAR_CTRL_BAR_IDX PCI_REBAR_CTRL_BAR_IDX +#define PCI_VF_REBAR_CTRL_NBAR_MASK PCI_REBAR_CTRL_NBAR_MASK +#define PCI_VF_REBAR_CTRL_BAR_SIZE PCI_REBAR_CTRL_BAR_SIZE + /* Data Link Feature */ #define PCI_DLF_CAP 0x04 /* Capabilities Register */ #define PCI_DLF_EXCHANGE_ENABLE 0x80000000 /* Data Link Feature Exchange Enable */ +/* Secondary PCIe Capability 8.0 GT/s */ +#define PCI_SECPCI_LE_CTRL 0x0c /* Lane Equalization Control Register */ + /* Physical Layer 16.0 GT/s */ #define PCI_PL_16GT_LE_CTRL 0x20 /* Lane Equalization Control Register */ #define PCI_PL_16GT_LE_CTRL_DSP_TX_PRESET_MASK 0x0000000F #define PCI_PL_16GT_LE_CTRL_USP_TX_PRESET_MASK 0x000000F0 #define PCI_PL_16GT_LE_CTRL_USP_TX_PRESET_SHIFT 4 +/* Physical Layer 32.0 GT/s */ +#define PCI_PL_32GT_LE_CTRL 0x20 /* Lane Equalization Control Register */ + +/* Physical Layer 64.0 GT/s */ +#define PCI_PL_64GT_LE_CTRL 0x20 /* Lane Equalization Control Register */ + /* Native PCIe Enclosure Management */ #define PCI_NPEM_CAP 0x04 /* NPEM capability register */ #define PCI_NPEM_CAP_CAPABLE 0x00000001 /* NPEM Capable */ diff --git a/include/standard-headers/linux/vhost_types.h b/include/standard-headers/linux/vhost_types.h index fd54044..79b53a9 100644 --- a/include/standard-headers/linux/vhost_types.h +++ b/include/standard-headers/linux/vhost_types.h @@ -110,6 +110,11 @@ struct vhost_msg_v2 { }; }; +struct vhost_features_array { + uint64_t count; /* number of entries present in features array */ + uint64_t features[] ; +}; + struct vhost_memory_region { uint64_t guest_phys_addr; uint64_t memory_size; /* bytes */ diff --git a/include/standard-headers/linux/virtio_gpu.h b/include/standard-headers/linux/virtio_gpu.h index 6459fdb..00cd3f0 100644 --- a/include/standard-headers/linux/virtio_gpu.h +++ b/include/standard-headers/linux/virtio_gpu.h @@ -309,8 +309,9 @@ struct virtio_gpu_cmd_submit { #define VIRTIO_GPU_CAPSET_VIRGL 1 #define VIRTIO_GPU_CAPSET_VIRGL2 2 -/* 3 is reserved for gfxstream */ +#define VIRTIO_GPU_CAPSET_GFXSTREAM_VULKAN 3 #define VIRTIO_GPU_CAPSET_VENUS 4 +#define VIRTIO_GPU_CAPSET_CROSS_DOMAIN 5 #define VIRTIO_GPU_CAPSET_DRM 6 /* VIRTIO_GPU_CMD_GET_CAPSET_INFO */ diff --git a/include/standard-headers/linux/virtio_ids.h b/include/standard-headers/linux/virtio_ids.h index 7aa2eb7..6c12db1 100644 --- a/include/standard-headers/linux/virtio_ids.h +++ b/include/standard-headers/linux/virtio_ids.h @@ -68,6 +68,7 @@ #define VIRTIO_ID_AUDIO_POLICY 39 /* virtio audio policy */ #define VIRTIO_ID_BT 40 /* virtio bluetooth */ #define VIRTIO_ID_GPIO 41 /* virtio gpio */ +#define VIRTIO_ID_SPI 45 /* virtio spi */ /* * Virtio Transitional IDs diff --git a/include/standard-headers/linux/virtio_net.h b/include/standard-headers/linux/virtio_net.h index 982e854..93abaae 100644 --- a/include/standard-headers/linux/virtio_net.h +++ b/include/standard-headers/linux/virtio_net.h @@ -70,6 +70,28 @@ * with the same MAC. */ #define VIRTIO_NET_F_SPEED_DUPLEX 63 /* Device set linkspeed and duplex */ +#define VIRTIO_NET_F_GUEST_UDP_TUNNEL_GSO 65 /* Driver can receive + * GSO-over-UDP-tunnel packets + */ +#define VIRTIO_NET_F_GUEST_UDP_TUNNEL_GSO_CSUM 66 /* Driver handles + * GSO-over-UDP-tunnel + * packets with partial csum + * for the outer header + */ +#define VIRTIO_NET_F_HOST_UDP_TUNNEL_GSO 67 /* Device can receive + * GSO-over-UDP-tunnel packets + */ +#define VIRTIO_NET_F_HOST_UDP_TUNNEL_GSO_CSUM 68 /* Device handles + * GSO-over-UDP-tunnel + * packets with partial csum + * for the outer header + */ + +/* Offloads bits corresponding to VIRTIO_NET_F_HOST_UDP_TUNNEL_GSO{,_CSUM} + * features + */ +#define VIRTIO_NET_F_GUEST_UDP_TUNNEL_GSO_MAPPED 46 +#define VIRTIO_NET_F_GUEST_UDP_TUNNEL_GSO_CSUM_MAPPED 47 #ifndef VIRTIO_NET_NO_LEGACY #define VIRTIO_NET_F_GSO 6 /* Host handles pkts w/ any GSO type */ @@ -131,12 +153,17 @@ struct virtio_net_hdr_v1 { #define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 /* Use csum_start, csum_offset */ #define VIRTIO_NET_HDR_F_DATA_VALID 2 /* Csum is valid */ #define VIRTIO_NET_HDR_F_RSC_INFO 4 /* rsc info in csum_ fields */ +#define VIRTIO_NET_HDR_F_UDP_TUNNEL_CSUM 8 /* UDP tunnel csum offload */ uint8_t flags; #define VIRTIO_NET_HDR_GSO_NONE 0 /* Not a GSO frame */ #define VIRTIO_NET_HDR_GSO_TCPV4 1 /* GSO frame, IPv4 TCP (TSO) */ #define VIRTIO_NET_HDR_GSO_UDP 3 /* GSO frame, IPv4 UDP (UFO) */ #define VIRTIO_NET_HDR_GSO_TCPV6 4 /* GSO frame, IPv6 TCP */ #define VIRTIO_NET_HDR_GSO_UDP_L4 5 /* GSO frame, IPv4& IPv6 UDP (USO) */ +#define VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV4 0x20 /* UDPv4 tunnel present */ +#define VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV6 0x40 /* UDPv6 tunnel present */ +#define VIRTIO_NET_HDR_GSO_UDP_TUNNEL (VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV4 | \ + VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV6) #define VIRTIO_NET_HDR_GSO_ECN 0x80 /* TCP has ECN set */ uint8_t gso_type; __virtio16 hdr_len; /* Ethernet + IP + tcp/udp hdrs */ @@ -181,6 +208,12 @@ struct virtio_net_hdr_v1_hash { uint16_t padding; }; +struct virtio_net_hdr_v1_hash_tunnel { + struct virtio_net_hdr_v1_hash hash_hdr; + uint16_t outer_th_offset; + uint16_t inner_nh_offset; +}; + #ifndef VIRTIO_NET_NO_LEGACY /* This header comes first in the scatter-gather list. * For legacy virtio, if VIRTIO_F_ANY_LAYOUT is not negotiated, it must diff --git a/include/standard-headers/linux/virtio_pci.h b/include/standard-headers/linux/virtio_pci.h index 91fec6f..09e964e 100644 --- a/include/standard-headers/linux/virtio_pci.h +++ b/include/standard-headers/linux/virtio_pci.h @@ -246,6 +246,7 @@ struct virtio_pci_cfg_cap { #define VIRTIO_ADMIN_CMD_LIST_USE 0x1 /* Admin command group type. */ +#define VIRTIO_ADMIN_GROUP_TYPE_SELF 0x0 #define VIRTIO_ADMIN_GROUP_TYPE_SRIOV 0x1 /* Transitional device admin command. */ diff --git a/include/standard-headers/uefi/uefi.h b/include/standard-headers/uefi/uefi.h new file mode 100644 index 0000000..5256349 --- /dev/null +++ b/include/standard-headers/uefi/uefi.h @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2025 Intel Corporation + * + * Author: Isaku Yamahata <isaku.yamahata at gmail.com> + * <isaku.yamahata at intel.com> + * Xiaoyao Li <xiaoyao.li@intel.com> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_I386_UEFI_H +#define HW_I386_UEFI_H + +/***************************************************************************/ +/* + * basic EFI definitions + * supplemented with UEFI Specification Version 2.8 (Errata A) + * released February 2020 + */ +/* UEFI integer is little endian */ + +typedef struct { + uint32_t Data1; + uint16_t Data2; + uint16_t Data3; + uint8_t Data4[8]; +} EFI_GUID; + +typedef enum { + EfiReservedMemoryType, + EfiLoaderCode, + EfiLoaderData, + EfiBootServicesCode, + EfiBootServicesData, + EfiRuntimeServicesCode, + EfiRuntimeServicesData, + EfiConventionalMemory, + EfiUnusableMemory, + EfiACPIReclaimMemory, + EfiACPIMemoryNVS, + EfiMemoryMappedIO, + EfiMemoryMappedIOPortSpace, + EfiPalCode, + EfiPersistentMemory, + EfiUnacceptedMemoryType, + EfiMaxMemoryType +} EFI_MEMORY_TYPE; + +#define EFI_HOB_HANDOFF_TABLE_VERSION 0x0009 + +#define EFI_HOB_TYPE_HANDOFF 0x0001 +#define EFI_HOB_TYPE_MEMORY_ALLOCATION 0x0002 +#define EFI_HOB_TYPE_RESOURCE_DESCRIPTOR 0x0003 +#define EFI_HOB_TYPE_GUID_EXTENSION 0x0004 +#define EFI_HOB_TYPE_FV 0x0005 +#define EFI_HOB_TYPE_CPU 0x0006 +#define EFI_HOB_TYPE_MEMORY_POOL 0x0007 +#define EFI_HOB_TYPE_FV2 0x0009 +#define EFI_HOB_TYPE_LOAD_PEIM_UNUSED 0x000A +#define EFI_HOB_TYPE_UEFI_CAPSULE 0x000B +#define EFI_HOB_TYPE_FV3 0x000C +#define EFI_HOB_TYPE_UNUSED 0xFFFE +#define EFI_HOB_TYPE_END_OF_HOB_LIST 0xFFFF + +typedef struct { + uint16_t HobType; + uint16_t HobLength; + uint32_t Reserved; +} EFI_HOB_GENERIC_HEADER; + +typedef uint64_t EFI_PHYSICAL_ADDRESS; +typedef uint32_t EFI_BOOT_MODE; + +typedef struct { + EFI_HOB_GENERIC_HEADER Header; + uint32_t Version; + EFI_BOOT_MODE BootMode; + EFI_PHYSICAL_ADDRESS EfiMemoryTop; + EFI_PHYSICAL_ADDRESS EfiMemoryBottom; + EFI_PHYSICAL_ADDRESS EfiFreeMemoryTop; + EFI_PHYSICAL_ADDRESS EfiFreeMemoryBottom; + EFI_PHYSICAL_ADDRESS EfiEndOfHobList; +} EFI_HOB_HANDOFF_INFO_TABLE; + +#define EFI_RESOURCE_SYSTEM_MEMORY 0x00000000 +#define EFI_RESOURCE_MEMORY_MAPPED_IO 0x00000001 +#define EFI_RESOURCE_IO 0x00000002 +#define EFI_RESOURCE_FIRMWARE_DEVICE 0x00000003 +#define EFI_RESOURCE_MEMORY_MAPPED_IO_PORT 0x00000004 +#define EFI_RESOURCE_MEMORY_RESERVED 0x00000005 +#define EFI_RESOURCE_IO_RESERVED 0x00000006 +#define EFI_RESOURCE_MEMORY_UNACCEPTED 0x00000007 +#define EFI_RESOURCE_MAX_MEMORY_TYPE 0x00000008 + +#define EFI_RESOURCE_ATTRIBUTE_PRESENT 0x00000001 +#define EFI_RESOURCE_ATTRIBUTE_INITIALIZED 0x00000002 +#define EFI_RESOURCE_ATTRIBUTE_TESTED 0x00000004 +#define EFI_RESOURCE_ATTRIBUTE_SINGLE_BIT_ECC 0x00000008 +#define EFI_RESOURCE_ATTRIBUTE_MULTIPLE_BIT_ECC 0x00000010 +#define EFI_RESOURCE_ATTRIBUTE_ECC_RESERVED_1 0x00000020 +#define EFI_RESOURCE_ATTRIBUTE_ECC_RESERVED_2 0x00000040 +#define EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED 0x00000080 +#define EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED 0x00000100 +#define EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED 0x00000200 +#define EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE 0x00000400 +#define EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE 0x00000800 +#define EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE 0x00001000 +#define EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE 0x00002000 +#define EFI_RESOURCE_ATTRIBUTE_16_BIT_IO 0x00004000 +#define EFI_RESOURCE_ATTRIBUTE_32_BIT_IO 0x00008000 +#define EFI_RESOURCE_ATTRIBUTE_64_BIT_IO 0x00010000 +#define EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED 0x00020000 +#define EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED 0x00040000 +#define EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE 0x00080000 +#define EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE 0x00100000 +#define EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE 0x00200000 +#define EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE 0x00400000 +#define EFI_RESOURCE_ATTRIBUTE_PERSISTENT 0x00800000 +#define EFI_RESOURCE_ATTRIBUTE_PERSISTABLE 0x01000000 +#define EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE 0x02000000 + +typedef uint32_t EFI_RESOURCE_TYPE; +typedef uint32_t EFI_RESOURCE_ATTRIBUTE_TYPE; + +typedef struct { + EFI_HOB_GENERIC_HEADER Header; + EFI_GUID Owner; + EFI_RESOURCE_TYPE ResourceType; + EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute; + EFI_PHYSICAL_ADDRESS PhysicalStart; + uint64_t ResourceLength; +} EFI_HOB_RESOURCE_DESCRIPTOR; + +typedef struct { + EFI_HOB_GENERIC_HEADER Header; + EFI_GUID Name; + + /* guid specific data follows */ +} EFI_HOB_GUID_TYPE; + +typedef struct { + EFI_HOB_GENERIC_HEADER Header; + EFI_PHYSICAL_ADDRESS BaseAddress; + uint64_t Length; +} EFI_HOB_FIRMWARE_VOLUME; + +typedef struct { + EFI_HOB_GENERIC_HEADER Header; + EFI_PHYSICAL_ADDRESS BaseAddress; + uint64_t Length; + EFI_GUID FvName; + EFI_GUID FileName; +} EFI_HOB_FIRMWARE_VOLUME2; + +typedef struct { + EFI_HOB_GENERIC_HEADER Header; + EFI_PHYSICAL_ADDRESS BaseAddress; + uint64_t Length; + uint32_t AuthenticationStatus; + bool ExtractedFv; + EFI_GUID FvName; + EFI_GUID FileName; +} EFI_HOB_FIRMWARE_VOLUME3; + +typedef struct { + EFI_HOB_GENERIC_HEADER Header; + uint8_t SizeOfMemorySpace; + uint8_t SizeOfIoSpace; + uint8_t Reserved[6]; +} EFI_HOB_CPU; + +typedef struct { + EFI_HOB_GENERIC_HEADER Header; +} EFI_HOB_MEMORY_POOL; + +typedef struct { + EFI_HOB_GENERIC_HEADER Header; + + EFI_PHYSICAL_ADDRESS BaseAddress; + uint64_t Length; +} EFI_HOB_UEFI_CAPSULE; + +#define EFI_HOB_OWNER_ZERO \ + ((EFI_GUID){ 0x00000000, 0x0000, 0x0000, \ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }) + +#endif diff --git a/include/system/accel-irq.h b/include/system/accel-irq.h new file mode 100644 index 0000000..671fb7d --- /dev/null +++ b/include/system/accel-irq.h @@ -0,0 +1,37 @@ +/* + * Accelerated irqchip abstraction + * + * Copyright Microsoft, Corp. 2025 + * + * Authors: Ziqiao Zhou <ziqiaozhou@microsoft.com> + * Magnus Kulke <magnuskulke@microsoft.com> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef SYSTEM_ACCEL_IRQ_H +#define SYSTEM_ACCEL_IRQ_H +#include "hw/pci/msi.h" +#include "qemu/osdep.h" +#include "system/kvm.h" +#include "system/mshv.h" + +static inline bool accel_msi_via_irqfd_enabled(void) +{ + return mshv_msi_via_irqfd_enabled() || kvm_msi_via_irqfd_enabled(); +} + +static inline bool accel_irqchip_is_split(void) +{ + return mshv_msi_via_irqfd_enabled() || kvm_irqchip_is_split(); +} + +int accel_irqchip_add_msi_route(KVMRouteChange *c, int vector, PCIDevice *dev); +int accel_irqchip_update_msi_route(int vector, MSIMessage msg, PCIDevice *dev); +void accel_irqchip_commit_route_changes(KVMRouteChange *c); +void accel_irqchip_commit_routes(void); +void accel_irqchip_release_virq(int virq); +int accel_irqchip_add_irqfd_notifier_gsi(EventNotifier *n, EventNotifier *rn, + int virq); +int accel_irqchip_remove_irqfd_notifier_gsi(EventNotifier *n, int virq); +#endif diff --git a/include/system/block-backend-global-state.h b/include/system/block-backend-global-state.h index 35b5e83..c384964 100644 --- a/include/system/block-backend-global-state.h +++ b/include/system/block-backend-global-state.h @@ -55,7 +55,7 @@ void monitor_remove_blk(BlockBackend *blk); BlockBackendPublic *blk_get_public(BlockBackend *blk); -void blk_remove_bs(BlockBackend *blk); +void GRAPH_UNLOCKED blk_remove_bs(BlockBackend *blk); int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp); int blk_replace_bs(BlockBackend *blk, BlockDriverState *new_bs, Error **errp); bool GRAPH_RDLOCK bdrv_has_blk(BlockDriverState *bs); @@ -78,8 +78,8 @@ int blk_make_zero(BlockBackend *blk, BdrvRequestFlags flags); void blk_aio_cancel(BlockAIOCB *acb); int blk_commit_all(void); bool blk_in_drain(BlockBackend *blk); -void blk_drain(BlockBackend *blk); -void blk_drain_all(void); +void GRAPH_UNLOCKED blk_drain(BlockBackend *blk); +void GRAPH_UNLOCKED blk_drain_all(void); void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error, BlockdevOnError on_write_error); bool blk_supports_write_perm(BlockBackend *blk); @@ -109,7 +109,7 @@ int blk_probe_blocksizes(BlockBackend *blk, BlockSizes *bsz); int blk_probe_geometry(BlockBackend *blk, HDGeometry *geo); void blk_set_io_limits(BlockBackend *blk, ThrottleConfig *cfg); -void blk_io_limits_disable(BlockBackend *blk); +void GRAPH_UNLOCKED blk_io_limits_disable(BlockBackend *blk); void blk_io_limits_enable(BlockBackend *blk, const char *group); void blk_io_limits_update_group(BlockBackend *blk, const char *group); void blk_set_force_allow_inactivate(BlockBackend *blk); diff --git a/include/system/block-backend-io.h b/include/system/block-backend-io.h index ba8dfcc..6d5ac47 100644 --- a/include/system/block-backend-io.h +++ b/include/system/block-backend-io.h @@ -116,6 +116,7 @@ BlockAIOCB *blk_abort_aio_request(BlockBackend *blk, void *opaque, int ret); uint32_t blk_get_request_alignment(BlockBackend *blk); +uint32_t blk_get_pwrite_zeroes_alignment(BlockBackend *blk); uint32_t blk_get_max_transfer(BlockBackend *blk); uint64_t blk_get_max_hw_transfer(BlockBackend *blk); diff --git a/include/system/confidential-guest-support.h b/include/system/confidential-guest-support.h index ea46b50..0cc8b26 100644 --- a/include/system/confidential-guest-support.h +++ b/include/system/confidential-guest-support.h @@ -19,6 +19,7 @@ #define QEMU_CONFIDENTIAL_GUEST_SUPPORT_H #include "qom/object.h" +#include "exec/hwaddr.h" #define TYPE_CONFIDENTIAL_GUEST_SUPPORT "confidential-guest-support" OBJECT_DECLARE_TYPE(ConfidentialGuestSupport, @@ -26,6 +27,40 @@ OBJECT_DECLARE_TYPE(ConfidentialGuestSupport, CONFIDENTIAL_GUEST_SUPPORT) +typedef enum ConfidentialGuestPlatformType { + CGS_PLATFORM_SEV, + CGS_PLATFORM_SEV_ES, + CGS_PLATFORM_SEV_SNP, +} ConfidentialGuestPlatformType; + +typedef enum ConfidentialGuestMemoryType { + CGS_MEM_RAM, + CGS_MEM_RESERVED, + CGS_MEM_ACPI, + CGS_MEM_NVS, + CGS_MEM_UNUSABLE, +} ConfidentialGuestMemoryType; + +typedef struct ConfidentialGuestMemoryMapEntry { + uint64_t gpa; + uint64_t size; + ConfidentialGuestMemoryType type; +} ConfidentialGuestMemoryMapEntry; + +typedef enum ConfidentialGuestPageType { + CGS_PAGE_TYPE_NORMAL, + CGS_PAGE_TYPE_VMSA, + CGS_PAGE_TYPE_ZERO, + CGS_PAGE_TYPE_UNMEASURED, + CGS_PAGE_TYPE_SECRETS, + CGS_PAGE_TYPE_CPUID, + CGS_PAGE_TYPE_REQUIRED_MEMORY, +} ConfidentialGuestPageType; + +typedef enum ConfidentialGuestPolicyType { + GUEST_POLICY_SEV, +} ConfidentialGuestPolicyType; + struct ConfidentialGuestSupport { Object parent; @@ -64,6 +99,59 @@ typedef struct ConfidentialGuestSupportClass { int (*kvm_init)(ConfidentialGuestSupport *cgs, Error **errp); int (*kvm_reset)(ConfidentialGuestSupport *cgs, Error **errp); + + /* + * Check to see if this confidential guest supports a particular + * platform or configuration. + * + * Return true if supported or false if not supported. + */ + bool (*check_support)(ConfidentialGuestPlatformType platform, + uint16_t platform_version, uint8_t highest_vtl, + uint64_t shared_gpa_boundary); + + /* + * Configure part of the state of a guest for a particular set of data, page + * type and gpa. This can be used for example to pre-populate and measure + * guest memory contents, define private ranges or set the initial CPU state + * for one or more CPUs. + * + * If memory_type is CGS_PAGE_TYPE_VMSA then ptr points to the initial CPU + * context for a virtual CPU. The format of the data depends on the type of + * confidential virtual machine. For example, for SEV-ES ptr will point to a + * vmcb_save_area structure that should be copied into guest memory at the + * address specified in gpa. The cpu_index parameter contains the index of + * the CPU the VMSA applies to. + */ + int (*set_guest_state)(hwaddr gpa, uint8_t *ptr, uint64_t len, + ConfidentialGuestPageType memory_type, + uint16_t cpu_index, Error **errp); + + /* + * Set the guest policy. The policy can be used to configure the + * confidential platform, such as if debug is enabled or not and can contain + * information about expected launch measurements, signed verification of + * guest configuration and other platform data. + * + * The format of the policy data is specific to each platform. For example, + * SEV-SNP uses a policy bitfield in the 'policy' argument and provides an + * ID block and ID authentication in the 'policy_data' parameters. The type + * of policy data is identified by the 'policy_type' argument. + */ + int (*set_guest_policy)(ConfidentialGuestPolicyType policy_type, + uint64_t policy, + void *policy_data1, uint32_t policy_data1_size, + void *policy_data2, uint32_t policy_data2_size, + Error **errp); + + /* + * Iterate the system memory map, getting the entry with the given index + * that can be populated into guest memory. + * + * Returns 0 for ok, 1 if the index is out of range and -1 on error. + */ + int (*get_mem_map_entry)(int index, ConfidentialGuestMemoryMapEntry *entry, + Error **errp); } ConfidentialGuestSupportClass; static inline int confidential_guest_kvm_init(ConfidentialGuestSupport *cgs, diff --git a/include/system/cpus.h b/include/system/cpus.h index 3226c76..508444c 100644 --- a/include/system/cpus.h +++ b/include/system/cpus.h @@ -7,11 +7,6 @@ void cpus_register_accel(const AccelOpsClass *i); /* return registers ops */ const AccelOpsClass *cpus_get_accel(void); -/* accel/dummy-cpus.c */ - -/* Create a dummy vcpu for AccelOpsClass->create_vcpu_thread */ -void dummy_start_vcpu_thread(CPUState *); - /* interface available for cpus accelerator threads */ /* For temporary buffers for forming a name */ @@ -22,8 +17,7 @@ bool cpu_work_list_empty(CPUState *cpu); bool cpu_thread_is_idle(CPUState *cpu); bool all_cpu_threads_idle(void); bool cpu_can_run(CPUState *cpu); -void qemu_wait_io_event_common(CPUState *cpu); -void qemu_wait_io_event(CPUState *cpu); +void qemu_process_cpu_events_common(CPUState *cpu); void cpu_thread_signal_created(CPUState *cpu); void cpu_thread_signal_destroyed(CPUState *cpu); void cpu_handle_guest_debug(CPUState *cpu); diff --git a/include/system/host_iommu_device.h b/include/system/host_iommu_device.h index 809cced..ab849a4 100644 --- a/include/system/host_iommu_device.h +++ b/include/system/host_iommu_device.h @@ -14,6 +14,13 @@ #include "qom/object.h" #include "qapi/error.h" +#ifdef CONFIG_LINUX +#include "linux/iommufd.h" + +typedef union VendorCaps { + struct iommu_hw_info_vtd vtd; + struct iommu_hw_info_arm_smmuv3 smmuv3; +} VendorCaps; /** * struct HostIOMMUDeviceCaps - Define host IOMMU device capabilities. @@ -22,11 +29,17 @@ * * @hw_caps: host platform IOMMU capabilities (e.g. on IOMMUFD this represents * the @out_capabilities value returned from IOMMU_GET_HW_INFO ioctl) + * + * @vendor_caps: host platform IOMMU vendor specific capabilities (e.g. on + * IOMMUFD this represents a user-space buffer filled by kernel + * with host IOMMU @type specific hardware information data) */ typedef struct HostIOMMUDeviceCaps { uint32_t type; uint64_t hw_caps; + VendorCaps vendor_caps; } HostIOMMUDeviceCaps; +#endif #define TYPE_HOST_IOMMU_DEVICE "host-iommu-device" OBJECT_DECLARE_TYPE(HostIOMMUDevice, HostIOMMUDeviceClass, HOST_IOMMU_DEVICE) @@ -38,7 +51,9 @@ struct HostIOMMUDevice { void *agent; /* pointer to agent device, ie. VFIO or VDPA device */ PCIBus *aliased_bus; int aliased_devfn; +#ifdef CONFIG_LINUX HostIOMMUDeviceCaps caps; +#endif }; /** diff --git a/include/system/hvf.h b/include/system/hvf.h index a9a502f..d3dcf08 100644 --- a/include/system/hvf.h +++ b/include/system/hvf.h @@ -14,10 +14,6 @@ #define HVF_H #include "qemu/accel.h" -#include "qemu/queue.h" -#include "exec/vaddr.h" -#include "qom/object.h" -#include "exec/vaddr.h" #ifdef COMPILING_PER_TARGET # ifdef CONFIG_HVF @@ -40,38 +36,4 @@ typedef struct HVFState HVFState; DECLARE_INSTANCE_CHECKER(HVFState, HVF_STATE, TYPE_HVF_ACCEL) -#ifdef COMPILING_PER_TARGET -struct hvf_sw_breakpoint { - vaddr pc; - vaddr saved_insn; - int use_count; - QTAILQ_ENTRY(hvf_sw_breakpoint) entry; -}; - -struct hvf_sw_breakpoint *hvf_find_sw_breakpoint(CPUState *cpu, - vaddr pc); -int hvf_sw_breakpoints_active(CPUState *cpu); - -int hvf_arch_insert_sw_breakpoint(CPUState *cpu, struct hvf_sw_breakpoint *bp); -int hvf_arch_remove_sw_breakpoint(CPUState *cpu, struct hvf_sw_breakpoint *bp); -int hvf_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type); -int hvf_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type); -void hvf_arch_remove_all_hw_breakpoints(void); - -/* - * hvf_update_guest_debug: - * @cs: CPUState for the CPU to update - * - * Update guest to enable or disable debugging. Per-arch specifics will be - * handled by calling down to hvf_arch_update_guest_debug. - */ -int hvf_update_guest_debug(CPUState *cpu); -void hvf_arch_update_guest_debug(CPUState *cpu); - -/* - * Return whether the guest supports debugging. - */ -bool hvf_arch_supports_guest_debug(void); -#endif /* COMPILING_PER_TARGET */ - #endif diff --git a/include/system/hvf_int.h b/include/system/hvf_int.h index 8c8b840..3d2be40 100644 --- a/include/system/hvf_int.h +++ b/include/system/hvf_int.h @@ -12,6 +12,9 @@ #define HVF_INT_H #include "qemu/queue.h" +#include "exec/vaddr.h" +#include "qom/object.h" +#include "accel/accel-ops.h" #ifdef __aarch64__ #include <Hypervisor/Hypervisor.h> @@ -43,7 +46,8 @@ typedef struct hvf_vcpu_caps { } hvf_vcpu_caps; struct HVFState { - AccelState parent; + AccelState parent_obj; + hvf_slot slots[32]; int num_slots; @@ -55,11 +59,12 @@ extern HVFState *hvf_state; struct AccelCPUState { hvf_vcpuid fd; - void *exit; +#ifdef __aarch64__ + hv_vcpu_exit_t *exit; bool vtimer_masked; sigset_t unblock_ipi_mask; bool guest_debug_enabled; - bool dirty; +#endif }; void assert_hvf_ok_impl(hv_return_t ret, const char *file, unsigned int line, @@ -68,12 +73,51 @@ void assert_hvf_ok_impl(hv_return_t ret, const char *file, unsigned int line, const char *hvf_return_string(hv_return_t ret); int hvf_arch_init(void); hv_return_t hvf_arch_vm_create(MachineState *ms, uint32_t pa_range); -int hvf_arch_init_vcpu(CPUState *cpu); -void hvf_arch_vcpu_destroy(CPUState *cpu); -int hvf_vcpu_exec(CPUState *); hvf_slot *hvf_find_overlap_slot(uint64_t, uint64_t); -int hvf_put_registers(CPUState *); -int hvf_get_registers(CPUState *); void hvf_kick_vcpu_thread(CPUState *cpu); +/* Must be called by the owning thread */ +int hvf_arch_init_vcpu(CPUState *cpu); +/* Must be called by the owning thread */ +void hvf_arch_vcpu_destroy(CPUState *cpu); +/* Must be called by the owning thread */ +int hvf_arch_vcpu_exec(CPUState *); +/* Must be called by the owning thread */ +int hvf_arch_put_registers(CPUState *); +/* Must be called by the owning thread */ +int hvf_arch_get_registers(CPUState *); +/* Must be called by the owning thread */ +void hvf_arch_update_guest_debug(CPUState *cpu); + +struct hvf_sw_breakpoint { + vaddr pc; + vaddr saved_insn; + int use_count; + QTAILQ_ENTRY(hvf_sw_breakpoint) entry; +}; + +struct hvf_sw_breakpoint *hvf_find_sw_breakpoint(CPUState *cpu, + vaddr pc); +int hvf_sw_breakpoints_active(CPUState *cpu); + +int hvf_arch_insert_sw_breakpoint(CPUState *cpu, struct hvf_sw_breakpoint *bp); +int hvf_arch_remove_sw_breakpoint(CPUState *cpu, struct hvf_sw_breakpoint *bp); +int hvf_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type); +int hvf_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type); +void hvf_arch_remove_all_hw_breakpoints(void); + +/* + * hvf_update_guest_debug: + * @cs: CPUState for the CPU to update + * + * Update guest to enable or disable debugging. Per-arch specifics will be + * handled by calling down to hvf_arch_update_guest_debug. + */ +int hvf_update_guest_debug(CPUState *cpu); + +/* + * Return whether the guest supports debugging. + */ +bool hvf_arch_supports_guest_debug(void); + #endif diff --git a/include/system/hw_accel.h b/include/system/hw_accel.h index 380e9e6..55497ed 100644 --- a/include/system/hw_accel.h +++ b/include/system/hw_accel.h @@ -14,12 +14,30 @@ #include "hw/core/cpu.h" #include "system/kvm.h" #include "system/hvf.h" +#include "system/mshv.h" #include "system/whpx.h" #include "system/nvmm.h" +/** + * cpu_synchronize_state: + * cpu_synchronize_pre_loadvm: + * @cpu: The vCPU to synchronize. + * + * Request to synchronize QEMU vCPU registers from the hardware accelerator + * (the hardware accelerator is the reference). + */ void cpu_synchronize_state(CPUState *cpu); +void cpu_synchronize_pre_loadvm(CPUState *cpu); + +/** + * cpu_synchronize_post_reset: + * cpu_synchronize_post_init: + * @cpu: The vCPU to synchronize. + * + * Request to synchronize QEMU vCPU registers to the hardware accelerator + * (QEMU is the reference). + */ void cpu_synchronize_post_reset(CPUState *cpu); void cpu_synchronize_post_init(CPUState *cpu); -void cpu_synchronize_pre_loadvm(CPUState *cpu); #endif /* QEMU_HW_ACCEL_H */ diff --git a/include/system/igvm-cfg.h b/include/system/igvm-cfg.h new file mode 100644 index 0000000..944f23a --- /dev/null +++ b/include/system/igvm-cfg.h @@ -0,0 +1,49 @@ +/* + * QEMU IGVM interface + * + * Copyright (C) 2024 SUSE + * + * Authors: + * Roy Hopkins <roy.hopkins@randomman.co.uk> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef QEMU_IGVM_CFG_H +#define QEMU_IGVM_CFG_H + +#include "qom/object.h" + +typedef struct IgvmCfg { + ObjectClass parent_class; + + /* + * filename: Filename that specifies a file that contains the configuration + * of the guest in Independent Guest Virtual Machine (IGVM) + * format. + */ + char *filename; +} IgvmCfg; + +typedef struct IgvmCfgClass { + ObjectClass parent_class; + + /* + * If an IGVM filename has been specified then process the IGVM file. + * Performs a no-op if no filename has been specified. + * If onlyVpContext is true then only the IGVM_VHT_VP_CONTEXT entries + * in the IGVM file will be processed, allowing information about the + * CPU state to be determined before processing the entire file. + * + * Returns 0 for ok and -1 on error. + */ + int (*process)(IgvmCfg *cfg, ConfidentialGuestSupport *cgs, + bool onlyVpContext, Error **errp); + +} IgvmCfgClass; + +#define TYPE_IGVM_CFG "igvm-cfg" + +OBJECT_DECLARE_TYPE(IgvmCfg, IgvmCfgClass, IGVM_CFG) + +#endif diff --git a/include/system/igvm.h b/include/system/igvm.h new file mode 100644 index 0000000..48ce206 --- /dev/null +++ b/include/system/igvm.h @@ -0,0 +1,29 @@ +/* + * QEMU IGVM configuration backend for Confidential Guests + * + * Copyright (C) 2023-2024 SUSE + * + * Authors: + * Roy Hopkins <roy.hopkins@randomman.co.uk> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef BACKENDS_IGVM_H +#define BACKENDS_IGVM_H + +#include "system/confidential-guest-support.h" +#include "system/igvm-cfg.h" +#include "qapi/error.h" + +int qigvm_process_file(IgvmCfg *igvm, ConfidentialGuestSupport *cgs, + bool onlyVpContext, Error **errp); + +/* x86 native */ +int qigvm_x86_get_mem_map_entry(int index, + ConfidentialGuestMemoryMapEntry *entry, + Error **errp); +int qigvm_x86_set_vp_context(void *data, int index, + Error **errp); + +#endif diff --git a/include/system/iommufd.h b/include/system/iommufd.h index cbab75b..a659f36 100644 --- a/include/system/iommufd.h +++ b/include/system/iommufd.h @@ -32,6 +32,7 @@ struct IOMMUFDBackend { /*< protected >*/ int fd; /* /dev/iommu file descriptor */ bool owned; /* is the /dev/iommu opened internally */ + Error *cpr_blocker;/* set if be does not support CPR */ uint32_t users; /*< public >*/ @@ -43,10 +44,13 @@ void iommufd_backend_disconnect(IOMMUFDBackend *be); bool iommufd_backend_alloc_ioas(IOMMUFDBackend *be, uint32_t *ioas_id, Error **errp); void iommufd_backend_free_id(IOMMUFDBackend *be, uint32_t id); +int iommufd_backend_map_file_dma(IOMMUFDBackend *be, uint32_t ioas_id, + hwaddr iova, uint64_t size, int fd, + unsigned long start, bool readonly); int iommufd_backend_map_dma(IOMMUFDBackend *be, uint32_t ioas_id, hwaddr iova, - ram_addr_t size, void *vaddr, bool readonly); + uint64_t size, void *vaddr, bool readonly); int iommufd_backend_unmap_dma(IOMMUFDBackend *be, uint32_t ioas_id, - hwaddr iova, ram_addr_t size); + hwaddr iova, uint64_t size); bool iommufd_backend_get_device_info(IOMMUFDBackend *be, uint32_t devid, uint32_t *type, void *data, uint32_t len, uint64_t *caps, Error **errp); @@ -61,6 +65,63 @@ bool iommufd_backend_get_dirty_bitmap(IOMMUFDBackend *be, uint32_t hwpt_id, uint64_t iova, ram_addr_t size, uint64_t page_size, uint64_t *data, Error **errp); +bool iommufd_backend_invalidate_cache(IOMMUFDBackend *be, uint32_t id, + uint32_t data_type, uint32_t entry_len, + uint32_t *entry_num, void *data, + Error **errp); + +bool iommufd_change_process_capable(IOMMUFDBackend *be); +bool iommufd_change_process(IOMMUFDBackend *be, Error **errp); #define TYPE_HOST_IOMMU_DEVICE_IOMMUFD TYPE_HOST_IOMMU_DEVICE "-iommufd" +OBJECT_DECLARE_TYPE(HostIOMMUDeviceIOMMUFD, HostIOMMUDeviceIOMMUFDClass, + HOST_IOMMU_DEVICE_IOMMUFD) + +/* Overload of the host IOMMU device for the iommufd backend */ +struct HostIOMMUDeviceIOMMUFD { + HostIOMMUDevice parent_obj; + + IOMMUFDBackend *iommufd; + uint32_t devid; + uint32_t hwpt_id; +}; + +struct HostIOMMUDeviceIOMMUFDClass { + HostIOMMUDeviceClass parent_class; + + /** + * @attach_hwpt: attach host IOMMU device to IOMMUFD hardware page table. + * VFIO and VDPA device can have different implementation. + * + * Mandatory callback. + * + * @idev: host IOMMU device backed by IOMMUFD backend. + * + * @hwpt_id: ID of IOMMUFD hardware page table. + * + * @errp: pass an Error out when attachment fails. + * + * Returns: true on success, false on failure. + */ + bool (*attach_hwpt)(HostIOMMUDeviceIOMMUFD *idev, uint32_t hwpt_id, + Error **errp); + /** + * @detach_hwpt: detach host IOMMU device from IOMMUFD hardware page table. + * VFIO and VDPA device can have different implementation. + * + * Mandatory callback. + * + * @idev: host IOMMU device backed by IOMMUFD backend. + * + * @errp: pass an Error out when attachment fails. + * + * Returns: true on success, false on failure. + */ + bool (*detach_hwpt)(HostIOMMUDeviceIOMMUFD *idev, Error **errp); +}; + +bool host_iommu_device_iommufd_attach_hwpt(HostIOMMUDeviceIOMMUFD *idev, + uint32_t hwpt_id, Error **errp); +bool host_iommu_device_iommufd_detach_hwpt(HostIOMMUDeviceIOMMUFD *idev, + Error **errp); #endif diff --git a/include/system/kvm.h b/include/system/kvm.h index b690dda..8f9eecf 100644 --- a/include/system/kvm.h +++ b/include/system/kvm.h @@ -42,6 +42,7 @@ extern bool kvm_gsi_routing_allowed; extern bool kvm_gsi_direct_mapping; extern bool kvm_readonly_mem_allowed; extern bool kvm_msi_use_devid; +extern bool kvm_pre_fault_memory_supported; #define kvm_enabled() (kvm_allowed) /** @@ -194,6 +195,7 @@ bool kvm_has_sync_mmu(void); int kvm_has_vcpu_events(void); int kvm_max_nested_state_length(void); int kvm_has_gsi_routing(void); +void kvm_close(void); /** * kvm_arm_supports_user_irq @@ -316,31 +318,6 @@ int kvm_create_device(KVMState *s, uint64_t type, bool test); bool kvm_device_supported(int vmfd, uint64_t type); /** - * kvm_create_vcpu - Gets a parked KVM vCPU or creates a KVM vCPU - * @cpu: QOM CPUState object for which KVM vCPU has to be fetched/created. - * - * @returns: 0 when success, errno (<0) when failed. - */ -int kvm_create_vcpu(CPUState *cpu); - -/** - * kvm_park_vcpu - Park QEMU KVM vCPU context - * @cpu: QOM CPUState object for which QEMU KVM vCPU context has to be parked. - * - * @returns: none - */ -void kvm_park_vcpu(CPUState *cpu); - -/** - * kvm_unpark_vcpu - unpark QEMU KVM vCPU context - * @s: KVM State - * @vcpu_id: Architecture vCPU ID of the parked vCPU - * - * @returns: KVM fd - */ -int kvm_unpark_vcpu(KVMState *s, unsigned long vcpu_id); - -/** * kvm_create_and_park_vcpu - Create and park a KVM vCPU * @cpu: QOM CPUState object for which KVM vCPU has to be created and parked. * @@ -363,19 +340,22 @@ int kvm_arch_process_async_events(CPUState *cpu); int kvm_arch_get_registers(CPUState *cpu, Error **errp); -/* state subset only touched by the VCPU itself during runtime */ -#define KVM_PUT_RUNTIME_STATE 1 -/* state subset modified during VCPU reset */ -#define KVM_PUT_RESET_STATE 2 -/* full state set, modified during initialization or on vmload */ -#define KVM_PUT_FULL_STATE 3 +typedef enum kvm_put_state { + /* state subset only touched by the VCPU itself during runtime */ + KVM_PUT_RUNTIME_STATE = 1, + /* state subset modified during VCPU reset */ + KVM_PUT_RESET_STATE = 2, + /* full state set, modified during initialization or on vmload */ + KVM_PUT_FULL_STATE = 3, +} KvmPutState; -int kvm_arch_put_registers(CPUState *cpu, int level, Error **errp); +int kvm_arch_put_registers(CPUState *cpu, KvmPutState level, Error **errp); int kvm_arch_get_default_type(MachineState *ms); int kvm_arch_init(MachineState *ms, KVMState *s); +int kvm_arch_pre_create_vcpu(CPUState *cpu, Error **errp); int kvm_arch_init_vcpu(CPUState *cpu); int kvm_arch_destroy_vcpu(CPUState *cpu); diff --git a/include/system/kvm_int.h b/include/system/kvm_int.h index 756a3c0..9247493 100644 --- a/include/system/kvm_int.h +++ b/include/system/kvm_int.h @@ -14,6 +14,7 @@ #include "qemu/accel.h" #include "qemu/queue.h" #include "system/kvm.h" +#include "accel/accel-ops.h" #include "hw/boards.h" #include "hw/i386/topology.h" #include "io/channel-socket.h" diff --git a/include/system/memory.h b/include/system/memory.h index fbbf4cf..3bd5ffa 100644 --- a/include/system/memory.h +++ b/include/system/memory.h @@ -19,7 +19,6 @@ #include "exec/memattrs.h" #include "exec/memop.h" #include "exec/ramlist.h" -#include "exec/tswap.h" #include "qemu/bswap.h" #include "qemu/queue.h" #include "qemu/int128.h" @@ -109,15 +108,34 @@ struct MemoryRegionSection { typedef struct IOMMUTLBEntry IOMMUTLBEntry; -/* See address_space_translate: bit 0 is read, bit 1 is write. */ +/* + * See address_space_translate: + * - bit 0 : read + * - bit 1 : write + * - bit 2 : exec + * - bit 3 : priv + * - bit 4 : global + * - bit 5 : untranslated only + */ typedef enum { IOMMU_NONE = 0, IOMMU_RO = 1, IOMMU_WO = 2, IOMMU_RW = 3, + IOMMU_EXEC = 4, + IOMMU_PRIV = 8, + IOMMU_GLOBAL = 16, + IOMMU_UNTRANSLATED_ONLY = 32, } IOMMUAccessFlags; -#define IOMMU_ACCESS_FLAG(r, w) (((r) ? IOMMU_RO : 0) | ((w) ? IOMMU_WO : 0)) +#define IOMMU_ACCESS_FLAG(r, w) (((r) ? IOMMU_RO : 0) | \ + ((w) ? IOMMU_WO : 0)) +#define IOMMU_ACCESS_FLAG_FULL(r, w, x, p, g, uo) \ + (IOMMU_ACCESS_FLAG(r, w) | \ + ((x) ? IOMMU_EXEC : 0) | \ + ((p) ? IOMMU_PRIV : 0) | \ + ((g) ? IOMMU_GLOBAL : 0) | \ + ((uo) ? IOMMU_UNTRANSLATED_ONLY : 0)) struct IOMMUTLBEntry { AddressSpace *target_as; @@ -125,6 +143,7 @@ struct IOMMUTLBEntry { hwaddr translated_addr; hwaddr addr_mask; /* 0xfff = 4k translation */ IOMMUAccessFlags perm; + uint32_t pasid; }; /* @@ -183,6 +202,7 @@ struct IOMMUNotifier { hwaddr start; hwaddr end; int iommu_idx; + void *opaque; QLIST_ENTRY(IOMMUNotifier) node; }; typedef struct IOMMUNotifier IOMMUNotifier; @@ -575,8 +595,20 @@ static inline void ram_discard_listener_init(RamDiscardListener *rdl, rdl->double_discard_supported = double_discard_supported; } -typedef int (*ReplayRamPopulate)(MemoryRegionSection *section, void *opaque); -typedef void (*ReplayRamDiscard)(MemoryRegionSection *section, void *opaque); +/** + * typedef ReplayRamDiscardState: + * + * The callback handler for #RamDiscardManagerClass.replay_populated/ + * #RamDiscardManagerClass.replay_discarded to invoke on populated/discarded + * parts. + * + * @section: the #MemoryRegionSection of populated/discarded part + * @opaque: pointer to forward to the callback + * + * Returns 0 on success, or a negative error if failed. + */ +typedef int (*ReplayRamDiscardState)(MemoryRegionSection *section, + void *opaque); /* * RamDiscardManagerClass: @@ -650,36 +682,38 @@ struct RamDiscardManagerClass { /** * @replay_populated: * - * Call the #ReplayRamPopulate callback for all populated parts within the - * #MemoryRegionSection via the #RamDiscardManager. + * Call the #ReplayRamDiscardState callback for all populated parts within + * the #MemoryRegionSection via the #RamDiscardManager. * * In case any call fails, no further calls are made. * * @rdm: the #RamDiscardManager * @section: the #MemoryRegionSection - * @replay_fn: the #ReplayRamPopulate callback + * @replay_fn: the #ReplayRamDiscardState callback * @opaque: pointer to forward to the callback * * Returns 0 on success, or a negative error if any notification failed. */ int (*replay_populated)(const RamDiscardManager *rdm, MemoryRegionSection *section, - ReplayRamPopulate replay_fn, void *opaque); + ReplayRamDiscardState replay_fn, void *opaque); /** * @replay_discarded: * - * Call the #ReplayRamDiscard callback for all discarded parts within the - * #MemoryRegionSection via the #RamDiscardManager. + * Call the #ReplayRamDiscardState callback for all discarded parts within + * the #MemoryRegionSection via the #RamDiscardManager. * * @rdm: the #RamDiscardManager * @section: the #MemoryRegionSection - * @replay_fn: the #ReplayRamDiscard callback + * @replay_fn: the #ReplayRamDiscardState callback * @opaque: pointer to forward to the callback + * + * Returns 0 on success, or a negative error if any notification failed. */ - void (*replay_discarded)(const RamDiscardManager *rdm, - MemoryRegionSection *section, - ReplayRamDiscard replay_fn, void *opaque); + int (*replay_discarded)(const RamDiscardManager *rdm, + MemoryRegionSection *section, + ReplayRamDiscardState replay_fn, void *opaque); /** * @register_listener: @@ -720,15 +754,41 @@ uint64_t ram_discard_manager_get_min_granularity(const RamDiscardManager *rdm, bool ram_discard_manager_is_populated(const RamDiscardManager *rdm, const MemoryRegionSection *section); +/** + * ram_discard_manager_replay_populated: + * + * A wrapper to call the #RamDiscardManagerClass.replay_populated callback + * of the #RamDiscardManager. + * + * @rdm: the #RamDiscardManager + * @section: the #MemoryRegionSection + * @replay_fn: the #ReplayRamDiscardState callback + * @opaque: pointer to forward to the callback + * + * Returns 0 on success, or a negative error if any notification failed. + */ int ram_discard_manager_replay_populated(const RamDiscardManager *rdm, MemoryRegionSection *section, - ReplayRamPopulate replay_fn, + ReplayRamDiscardState replay_fn, void *opaque); -void ram_discard_manager_replay_discarded(const RamDiscardManager *rdm, - MemoryRegionSection *section, - ReplayRamDiscard replay_fn, - void *opaque); +/** + * ram_discard_manager_replay_discarded: + * + * A wrapper to call the #RamDiscardManagerClass.replay_discarded callback + * of the #RamDiscardManager. + * + * @rdm: the #RamDiscardManager + * @section: the #MemoryRegionSection + * @replay_fn: the #ReplayRamDiscardState callback + * @opaque: pointer to forward to the callback + * + * Returns 0 on success, or a negative error if any notification failed. + */ +int ram_discard_manager_replay_discarded(const RamDiscardManager *rdm, + MemoryRegionSection *section, + ReplayRamDiscardState replay_fn, + void *opaque); void ram_discard_manager_register_listener(RamDiscardManager *rdm, RamDiscardListener *rdl, @@ -738,21 +798,20 @@ void ram_discard_manager_unregister_listener(RamDiscardManager *rdm, RamDiscardListener *rdl); /** - * memory_get_xlat_addr: Extract addresses from a TLB entry + * memory_translate_iotlb: Extract addresses from a TLB entry. + * Called with rcu_read_lock held. * * @iotlb: pointer to an #IOMMUTLBEntry - * @vaddr: virtual address - * @ram_addr: RAM address - * @read_only: indicates if writes are allowed - * @mr_has_discard_manager: indicates memory is controlled by a - * RamDiscardManager + * @xlat_p: return the offset of the entry from the start of the returned + * MemoryRegion. * @errp: pointer to Error*, to store an error if it happens. * - * Return: true on success, else false setting @errp with error. + * Return: On success, return the MemoryRegion containing the @iotlb translated + * addr. The MemoryRegion must not be accessed after rcu_read_unlock. + * On failure, return NULL, setting @errp with error. */ -bool memory_get_xlat_addr(IOMMUTLBEntry *iotlb, void **vaddr, - ram_addr_t *ram_addr, bool *read_only, - bool *mr_has_discard_manager, Error **errp); +MemoryRegion *memory_translate_iotlb(IOMMUTLBEntry *iotlb, hwaddr *xlat_p, + Error **errp); typedef struct CoalescedMemoryRange CoalescedMemoryRange; typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd; @@ -774,6 +833,7 @@ struct MemoryRegion { bool nonvolatile; bool rom_device; bool flush_coalesced_mmio; + bool lockless_io; bool unmergeable; uint8_t dirty_log_mask; bool is_iommu; @@ -1212,6 +1272,36 @@ MemoryRegionSection *memory_region_section_new_copy(MemoryRegionSection *s); void memory_region_section_free_copy(MemoryRegionSection *s); /** + * memory_region_section_intersect_range: Adjust the memory section to cover + * the intersection with the given range. + * + * @s: the #MemoryRegionSection to be adjusted + * @offset: the offset of the given range in the memory region + * @size: the size of the given range + * + * Returns false if the intersection is empty, otherwise returns true. + */ +static inline bool memory_region_section_intersect_range(MemoryRegionSection *s, + uint64_t offset, + uint64_t size) +{ + uint64_t start = MAX(s->offset_within_region, offset); + Int128 end = int128_min(int128_add(int128_make64(s->offset_within_region), + s->size), + int128_add(int128_make64(offset), + int128_make64(size))); + + if (int128_le(end, int128_make64(start))) { + return false; + } + + s->offset_within_address_space += start - s->offset_within_region; + s->offset_within_region = start; + s->size = int128_sub(end, int128_make64(start)); + return true; +} + +/** * memory_region_init: Initialize a memory region * * The region typically acts as a container for other memory regions. Use @@ -2253,6 +2343,17 @@ void memory_region_set_flush_coalesced(MemoryRegion *mr); void memory_region_clear_flush_coalesced(MemoryRegion *mr); /** + * memory_region_enable_lockless_io: Enable lockless (BQL free) acceess. + * + * Enable BQL-free access for devices that are well prepared to handle + * locking during I/O themselves: either by doing fine grained locking or + * by providing lock-free I/O schemes. + * + * @mr: the memory region to be updated. + */ +void memory_region_enable_lockless_io(MemoryRegion *mr); + +/** * memory_region_add_eventfd: Request an eventfd to be triggered when a word * is written to a location. * @@ -2469,13 +2570,13 @@ static inline bool memory_region_has_ram_discard_manager(MemoryRegion *mr) * * This function must not be called for a mapped #MemoryRegion, a #MemoryRegion * that does not cover RAM, or a #MemoryRegion that already has a - * #RamDiscardManager assigned. + * #RamDiscardManager assigned. Return 0 if the rdm is set successfully. * * @mr: the #MemoryRegion * @rdm: #RamDiscardManager to set */ -void memory_region_set_ram_discard_manager(MemoryRegion *mr, - RamDiscardManager *rdm); +int memory_region_set_ram_discard_manager(MemoryRegion *mr, + RamDiscardManager *rdm); /** * memory_region_find: translate an address/size relative to a @@ -2626,15 +2727,33 @@ void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name); /** * address_space_destroy: destroy an address space * - * Releases all resources associated with an address space. After an address space - * is destroyed, its root memory region (given by address_space_init()) may be destroyed - * as well. + * Releases all resources associated with an address space. After an + * address space is destroyed, the reference the AddressSpace had to + * its root memory region is dropped, which may result in the + * destruction of that memory region as well. + * + * Note that destruction of the AddressSpace is done via RCU; + * it is therefore not valid to free the memory the AddressSpace + * struct is in until after that RCU callback has completed. + * If you want to g_free() the AddressSpace after destruction you + * can do that with address_space_destroy_free(). * * @as: address space to be destroyed */ void address_space_destroy(AddressSpace *as); /** + * address_space_destroy_free: destroy an address space and free it + * + * This does the same thing as address_space_destroy(), and then also + * frees (via g_free()) the AddressSpace itself once the destruction + * is complete. + * + * @as: address space to be destroyed + */ +void address_space_destroy_free(AddressSpace *as); + +/** * address_space_remove_listeners: unregister all listeners of an address space * * Removes all callbacks previously registered with memory_listener_register() @@ -2876,6 +2995,8 @@ void address_space_cache_invalidate(MemoryRegionCache *cache, */ void address_space_cache_destroy(MemoryRegionCache *cache); +void address_space_flush_icache_range(AddressSpace *as, hwaddr addr, hwaddr len); + /* address_space_get_iotlb_entry: translate an address into an IOTLB * entry. Should be called from an RCU critical section. */ @@ -2928,6 +3049,15 @@ static inline MemoryRegion *address_space_translate(AddressSpace *as, bool address_space_access_valid(AddressSpace *as, hwaddr addr, hwaddr len, bool is_write, MemTxAttrs attrs); +/** + * address_space_is_io: check whether an guest physical addresses + * whithin an address space is I/O memory. + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + */ +bool address_space_is_io(AddressSpace *as, hwaddr addr); + /* address_space_map: map a physical memory region into a host virtual address * * May map a subset of the requested range, given by and returned in @plen. diff --git a/include/system/mshv.h b/include/system/mshv.h new file mode 100644 index 0000000..8b1fc20 --- /dev/null +++ b/include/system/mshv.h @@ -0,0 +1,64 @@ +/* + * QEMU MSHV support + * + * Copyright Microsoft, Corp. 2025 + * + * Authors: Ziqiao Zhou <ziqiaozhou@microsoft.com> + * Magnus Kulke <magnuskulke@microsoft.com> + * Jinank Jain <jinankjain@microsoft.com> + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + */ + +#ifndef QEMU_MSHV_H +#define QEMU_MSHV_H + +#include "qemu/osdep.h" +#include "qemu/accel.h" +#include "hw/hyperv/hyperv-proto.h" +#include "hw/hyperv/hvhdk.h" +#include "hw/hyperv/hvgdk_mini.h" +#include "qapi/qapi-types-common.h" +#include "system/memory.h" +#include "accel/accel-ops.h" + +#ifdef COMPILING_PER_TARGET +#ifdef CONFIG_MSHV +#include <linux/mshv.h> +#define CONFIG_MSHV_IS_POSSIBLE +#endif +#else +#define CONFIG_MSHV_IS_POSSIBLE +#endif + +#define MSHV_MAX_MSI_ROUTES 4096 + +#define MSHV_PAGE_SHIFT 12 + +#ifdef CONFIG_MSHV_IS_POSSIBLE +extern bool mshv_allowed; +#define mshv_enabled() (mshv_allowed) +#define mshv_msi_via_irqfd_enabled() mshv_enabled() +#else /* CONFIG_MSHV_IS_POSSIBLE */ +#define mshv_enabled() false +#define mshv_msi_via_irqfd_enabled() mshv_enabled() +#endif + +typedef struct MshvState MshvState; +extern MshvState *mshv_state; + +/* interrupt */ +int mshv_request_interrupt(MshvState *mshv_state, uint32_t interrupt_type, uint32_t vector, + uint32_t vp_index, bool logical_destination_mode, + bool level_triggered); + +int mshv_irqchip_add_msi_route(int vector, PCIDevice *dev); +int mshv_irqchip_update_msi_route(int virq, MSIMessage msg, PCIDevice *dev); +void mshv_irqchip_commit_routes(void); +void mshv_irqchip_release_virq(int virq); +int mshv_irqchip_add_irqfd_notifier_gsi(const EventNotifier *n, + const EventNotifier *rn, int virq); +int mshv_irqchip_remove_irqfd_notifier_gsi(const EventNotifier *n, int virq); + +#endif diff --git a/include/system/mshv_int.h b/include/system/mshv_int.h new file mode 100644 index 0000000..490563c --- /dev/null +++ b/include/system/mshv_int.h @@ -0,0 +1,155 @@ +/* + * QEMU MSHV support + * + * Copyright Microsoft, Corp. 2025 + * + * Authors: Ziqiao Zhou <ziqiaozhou@microsoft.com> + * Magnus Kulke <magnuskulke@microsoft.com> + * Jinank Jain <jinankjain@microsoft.com> + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + */ + +#ifndef QEMU_MSHV_INT_H +#define QEMU_MSHV_INT_H + +#define MSHV_MSR_ENTRIES_COUNT 64 + +#define MSHV_MAX_MEM_SLOTS 32 + +typedef struct hyperv_message hv_message; + +typedef struct MshvHvCallArgs { + void *base; + void *input_page; + void *output_page; +} MshvHvCallArgs; + +struct AccelCPUState { + int cpufd; + bool dirty; + MshvHvCallArgs hvcall_args; +}; + +typedef struct MshvMemoryListener { + MemoryListener listener; + int as_id; +} MshvMemoryListener; + +typedef struct MshvAddressSpace { + MshvMemoryListener *ml; + AddressSpace *as; +} MshvAddressSpace; + +typedef struct MshvMemorySlotManager { + size_t n_slots; + GList *slots; + QemuMutex mutex; +} MshvMemorySlotManager; + +struct MshvState { + AccelState parent_obj; + int vm; + MshvMemoryListener memory_listener; + /* number of listeners */ + int nr_as; + MshvAddressSpace *as; + int fd; + MshvMemorySlotManager msm; +}; + +typedef struct MshvMsiControl { + bool updated; + GHashTable *gsi_routes; +} MshvMsiControl; + +#define mshv_vcpufd(cpu) (cpu->accel->cpufd) + +/* cpu */ +typedef struct MshvFPU { + uint8_t fpr[8][16]; + uint16_t fcw; + uint16_t fsw; + uint8_t ftwx; + uint8_t pad1; + uint16_t last_opcode; + uint64_t last_ip; + uint64_t last_dp; + uint8_t xmm[16][16]; + uint32_t mxcsr; + uint32_t pad2; +} MshvFPU; + +typedef enum MshvVmExit { + MshvVmExitIgnore = 0, + MshvVmExitShutdown = 1, + MshvVmExitSpecial = 2, +} MshvVmExit; + +typedef enum MshvRemapResult { + MshvRemapOk = 0, + MshvRemapNoMapping = 1, + MshvRemapNoOverlap = 2, +} MshvRemapResult; + +void mshv_init_mmio_emu(void); +int mshv_create_vcpu(int vm_fd, uint8_t vp_index, int *cpu_fd); +void mshv_remove_vcpu(int vm_fd, int cpu_fd); +int mshv_configure_vcpu(const CPUState *cpu, const MshvFPU *fpu, uint64_t xcr0); +int mshv_get_standard_regs(CPUState *cpu); +int mshv_get_special_regs(CPUState *cpu); +int mshv_run_vcpu(int vm_fd, CPUState *cpu, hv_message *msg, MshvVmExit *exit); +int mshv_load_regs(CPUState *cpu); +int mshv_store_regs(CPUState *cpu); +int mshv_set_generic_regs(const CPUState *cpu, const hv_register_assoc *assocs, + size_t n_regs); +int mshv_arch_put_registers(const CPUState *cpu); +void mshv_arch_init_vcpu(CPUState *cpu); +void mshv_arch_destroy_vcpu(CPUState *cpu); +void mshv_arch_amend_proc_features( + union hv_partition_synthetic_processor_features *features); +int mshv_arch_post_init_vm(int vm_fd); + +#if defined COMPILING_PER_TARGET && defined CONFIG_MSHV_IS_POSSIBLE +int mshv_hvcall(int fd, const struct mshv_root_hvcall *args); +#endif + +/* memory */ +typedef struct MshvMemorySlot { + uint64_t guest_phys_addr; + uint64_t memory_size; + uint64_t userspace_addr; + bool readonly; + bool mapped; +} MshvMemorySlot; + +MshvRemapResult mshv_remap_overlap_region(int vm_fd, uint64_t gpa); +int mshv_guest_mem_read(uint64_t gpa, uint8_t *data, uintptr_t size, + bool is_secure_mode, bool instruction_fetch); +int mshv_guest_mem_write(uint64_t gpa, const uint8_t *data, uintptr_t size, + bool is_secure_mode); +void mshv_set_phys_mem(MshvMemoryListener *mml, MemoryRegionSection *section, + bool add); +void mshv_init_memory_slot_manager(MshvState *mshv_state); + +/* msr */ +typedef struct MshvMsrEntry { + uint32_t index; + uint32_t reserved; + uint64_t data; +} MshvMsrEntry; + +typedef struct MshvMsrEntries { + MshvMsrEntry entries[MSHV_MSR_ENTRIES_COUNT]; + uint32_t nmsrs; +} MshvMsrEntries; + +int mshv_configure_msr(const CPUState *cpu, const MshvMsrEntry *msrs, + size_t n_msrs); + +/* interrupt */ +void mshv_init_msicontrol(void); +int mshv_reserve_ioapic_msi_routes(int vm_fd); + +#endif diff --git a/include/system/nvmm.h b/include/system/nvmm.h index 6971ddb..7390def 100644 --- a/include/system/nvmm.h +++ b/include/system/nvmm.h @@ -13,17 +13,18 @@ #define QEMU_NVMM_H #ifdef COMPILING_PER_TARGET - -#ifdef CONFIG_NVMM - -int nvmm_enabled(void); - -#else /* CONFIG_NVMM */ - -#define nvmm_enabled() (0) - -#endif /* CONFIG_NVMM */ - +# ifdef CONFIG_NVMM +# define CONFIG_NVMM_IS_POSSIBLE +# endif /* !CONFIG_NVMM */ +#else +# define CONFIG_NVMM_IS_POSSIBLE #endif /* COMPILING_PER_TARGET */ +#ifdef CONFIG_NVMM_IS_POSSIBLE +extern bool nvmm_allowed; +#define nvmm_enabled() (nvmm_allowed) +#else /* !CONFIG_NVMM_IS_POSSIBLE */ +#define nvmm_enabled() 0 +#endif /* !CONFIG_NVMM_IS_POSSIBLE */ + #endif /* QEMU_NVMM_H */ diff --git a/include/system/os-win32.h b/include/system/os-win32.h index 3aa6cee..22d72ba 100644 --- a/include/system/os-win32.h +++ b/include/system/os-win32.h @@ -168,11 +168,14 @@ static inline void qemu_funlockfile(FILE *f) #endif } -/* Helper for WSAEventSelect, to report errors */ +/* Helpers for WSAEventSelect() */ bool qemu_socket_select(int sockfd, WSAEVENT hEventObject, long lNetworkEvents, Error **errp); +void qemu_socket_select_nofail(int sockfd, WSAEVENT hEventObject, + long lNetworkEvents); bool qemu_socket_unselect(int sockfd, Error **errp); +void qemu_socket_unselect_nofail(int sockfd); /* We wrap all the sockets functions so that we can set errno based on * WSAGetLastError(), and use file-descriptors instead of SOCKET. diff --git a/include/system/physmem.h b/include/system/physmem.h new file mode 100644 index 0000000..879f6ea --- /dev/null +++ b/include/system/physmem.h @@ -0,0 +1,54 @@ +/* + * QEMU physical memory interfaces (target independent). + * + * Copyright (c) 2003 Fabrice Bellard + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef QEMU_SYSTEM_PHYSMEM_H +#define QEMU_SYSTEM_PHYSMEM_H + +#include "exec/hwaddr.h" +#include "exec/ramlist.h" + +#define DIRTY_CLIENTS_ALL ((1 << DIRTY_MEMORY_NUM) - 1) +#define DIRTY_CLIENTS_NOCODE (DIRTY_CLIENTS_ALL & ~(1 << DIRTY_MEMORY_CODE)) + +bool physical_memory_get_dirty_flag(ram_addr_t addr, unsigned client); + +bool physical_memory_is_clean(ram_addr_t addr); + +uint8_t physical_memory_range_includes_clean(ram_addr_t start, + ram_addr_t length, + uint8_t mask); + +void physical_memory_set_dirty_flag(ram_addr_t addr, unsigned client); + +void physical_memory_set_dirty_range(ram_addr_t start, ram_addr_t length, + uint8_t mask); + +/* + * Contrary to physical_memory_sync_dirty_bitmap() this function returns + * the number of dirty pages in @bitmap passed as argument. On the other hand, + * physical_memory_sync_dirty_bitmap() returns newly dirtied pages that + * weren't set in the global migration bitmap. + */ +uint64_t physical_memory_set_dirty_lebitmap(unsigned long *bitmap, + ram_addr_t start, + ram_addr_t pages); + +void physical_memory_dirty_bits_cleared(ram_addr_t start, ram_addr_t length); + +bool physical_memory_test_and_clear_dirty(ram_addr_t start, + ram_addr_t length, + unsigned client); + +DirtyBitmapSnapshot * +physical_memory_snapshot_and_clear_dirty(MemoryRegion *mr, hwaddr offset, + hwaddr length, unsigned client); + +bool physical_memory_snapshot_get_dirty(DirtyBitmapSnapshot *snap, + ram_addr_t start, + ram_addr_t length); + +#endif diff --git a/include/system/qtest.h b/include/system/qtest.h index 84b1f8c..7f6dc01 100644 --- a/include/system/qtest.h +++ b/include/system/qtest.h @@ -23,8 +23,8 @@ static inline bool qtest_enabled(void) return qtest_allowed; } -void G_GNUC_PRINTF(2, 3) qtest_sendf(CharBackend *chr, const char *fmt, ...); -void qtest_set_command_cb(bool (*pc_cb)(CharBackend *chr, gchar **words)); +void G_GNUC_PRINTF(2, 3) qtest_sendf(CharFrontend *chr, const char *fmt, ...); +void qtest_set_command_cb(bool (*pc_cb)(CharFrontend *chr, gchar **words)); bool qtest_driver(void); void qtest_server_init(const char *qtest_chrdev, const char *qtest_log, Error **errp); diff --git a/include/system/ram_addr.h b/include/system/ram_addr.h index 15a1b1a..6834859 100644 --- a/include/system/ram_addr.h +++ b/include/system/ram_addr.h @@ -19,17 +19,9 @@ #ifndef SYSTEM_RAM_ADDR_H #define SYSTEM_RAM_ADDR_H -#include "system/xen.h" -#include "system/tcg.h" -#include "exec/cputlb.h" -#include "exec/ramlist.h" #include "system/ramblock.h" -#include "system/memory.h" #include "exec/target_page.h" -#include "qemu/rcu.h" - #include "exec/hwaddr.h" -#include "exec/cpu-common.h" extern uint64_t total_dirty_pages; @@ -80,17 +72,6 @@ static inline bool clear_bmap_test_and_clear(RAMBlock *rb, uint64_t page) return bitmap_test_and_clear(rb->clear_bmap, page >> shift, 1); } -static inline bool offset_in_ramblock(RAMBlock *b, ram_addr_t offset) -{ - return (b && b->host && offset < b->used_length) ? true : false; -} - -static inline void *ramblock_ptr(RAMBlock *block, ram_addr_t offset) -{ - assert(offset_in_ramblock(block, offset)); - return (char *)block->host + offset; -} - static inline unsigned long int ramblock_recv_bitmap_offset(void *host_addr, RAMBlock *rb) { @@ -99,8 +80,6 @@ static inline unsigned long int ramblock_recv_bitmap_offset(void *host_addr, return host_addr_offset >> TARGET_PAGE_BITS; } -bool ramblock_is_pmem(RAMBlock *rb); - /** * qemu_ram_alloc_from_file, * qemu_ram_alloc_from_fd: Allocate a ram block from the specified backing @@ -153,409 +132,4 @@ static inline void qemu_ram_block_writeback(RAMBlock *block) qemu_ram_msync(block, 0, block->used_length); } -#define DIRTY_CLIENTS_ALL ((1 << DIRTY_MEMORY_NUM) - 1) -#define DIRTY_CLIENTS_NOCODE (DIRTY_CLIENTS_ALL & ~(1 << DIRTY_MEMORY_CODE)) - -static inline bool cpu_physical_memory_get_dirty(ram_addr_t start, - ram_addr_t length, - unsigned client) -{ - DirtyMemoryBlocks *blocks; - unsigned long end, page; - unsigned long idx, offset, base; - bool dirty = false; - - assert(client < DIRTY_MEMORY_NUM); - - end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS; - page = start >> TARGET_PAGE_BITS; - - WITH_RCU_READ_LOCK_GUARD() { - blocks = qatomic_rcu_read(&ram_list.dirty_memory[client]); - - idx = page / DIRTY_MEMORY_BLOCK_SIZE; - offset = page % DIRTY_MEMORY_BLOCK_SIZE; - base = page - offset; - while (page < end) { - unsigned long next = MIN(end, base + DIRTY_MEMORY_BLOCK_SIZE); - unsigned long num = next - base; - unsigned long found = find_next_bit(blocks->blocks[idx], - num, offset); - if (found < num) { - dirty = true; - break; - } - - page = next; - idx++; - offset = 0; - base += DIRTY_MEMORY_BLOCK_SIZE; - } - } - - return dirty; -} - -static inline bool cpu_physical_memory_all_dirty(ram_addr_t start, - ram_addr_t length, - unsigned client) -{ - DirtyMemoryBlocks *blocks; - unsigned long end, page; - unsigned long idx, offset, base; - bool dirty = true; - - assert(client < DIRTY_MEMORY_NUM); - - end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS; - page = start >> TARGET_PAGE_BITS; - - RCU_READ_LOCK_GUARD(); - - blocks = qatomic_rcu_read(&ram_list.dirty_memory[client]); - - idx = page / DIRTY_MEMORY_BLOCK_SIZE; - offset = page % DIRTY_MEMORY_BLOCK_SIZE; - base = page - offset; - while (page < end) { - unsigned long next = MIN(end, base + DIRTY_MEMORY_BLOCK_SIZE); - unsigned long num = next - base; - unsigned long found = find_next_zero_bit(blocks->blocks[idx], num, offset); - if (found < num) { - dirty = false; - break; - } - - page = next; - idx++; - offset = 0; - base += DIRTY_MEMORY_BLOCK_SIZE; - } - - return dirty; -} - -static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr, - unsigned client) -{ - return cpu_physical_memory_get_dirty(addr, 1, client); -} - -static inline bool cpu_physical_memory_is_clean(ram_addr_t addr) -{ - bool vga = cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_VGA); - bool code = cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_CODE); - bool migration = - cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_MIGRATION); - return !(vga && code && migration); -} - -static inline uint8_t cpu_physical_memory_range_includes_clean(ram_addr_t start, - ram_addr_t length, - uint8_t mask) -{ - uint8_t ret = 0; - - if (mask & (1 << DIRTY_MEMORY_VGA) && - !cpu_physical_memory_all_dirty(start, length, DIRTY_MEMORY_VGA)) { - ret |= (1 << DIRTY_MEMORY_VGA); - } - if (mask & (1 << DIRTY_MEMORY_CODE) && - !cpu_physical_memory_all_dirty(start, length, DIRTY_MEMORY_CODE)) { - ret |= (1 << DIRTY_MEMORY_CODE); - } - if (mask & (1 << DIRTY_MEMORY_MIGRATION) && - !cpu_physical_memory_all_dirty(start, length, DIRTY_MEMORY_MIGRATION)) { - ret |= (1 << DIRTY_MEMORY_MIGRATION); - } - return ret; -} - -static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr, - unsigned client) -{ - unsigned long page, idx, offset; - DirtyMemoryBlocks *blocks; - - assert(client < DIRTY_MEMORY_NUM); - - page = addr >> TARGET_PAGE_BITS; - idx = page / DIRTY_MEMORY_BLOCK_SIZE; - offset = page % DIRTY_MEMORY_BLOCK_SIZE; - - RCU_READ_LOCK_GUARD(); - - blocks = qatomic_rcu_read(&ram_list.dirty_memory[client]); - - set_bit_atomic(offset, blocks->blocks[idx]); -} - -static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start, - ram_addr_t length, - uint8_t mask) -{ - DirtyMemoryBlocks *blocks[DIRTY_MEMORY_NUM]; - unsigned long end, page; - unsigned long idx, offset, base; - int i; - - if (!mask && !xen_enabled()) { - return; - } - - end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS; - page = start >> TARGET_PAGE_BITS; - - WITH_RCU_READ_LOCK_GUARD() { - for (i = 0; i < DIRTY_MEMORY_NUM; i++) { - blocks[i] = qatomic_rcu_read(&ram_list.dirty_memory[i]); - } - - idx = page / DIRTY_MEMORY_BLOCK_SIZE; - offset = page % DIRTY_MEMORY_BLOCK_SIZE; - base = page - offset; - while (page < end) { - unsigned long next = MIN(end, base + DIRTY_MEMORY_BLOCK_SIZE); - - if (likely(mask & (1 << DIRTY_MEMORY_MIGRATION))) { - bitmap_set_atomic(blocks[DIRTY_MEMORY_MIGRATION]->blocks[idx], - offset, next - page); - } - if (unlikely(mask & (1 << DIRTY_MEMORY_VGA))) { - bitmap_set_atomic(blocks[DIRTY_MEMORY_VGA]->blocks[idx], - offset, next - page); - } - if (unlikely(mask & (1 << DIRTY_MEMORY_CODE))) { - bitmap_set_atomic(blocks[DIRTY_MEMORY_CODE]->blocks[idx], - offset, next - page); - } - - page = next; - idx++; - offset = 0; - base += DIRTY_MEMORY_BLOCK_SIZE; - } - } - - if (xen_enabled()) { - xen_hvm_modified_memory(start, length); - } -} - -#if !defined(_WIN32) - -/* - * Contrary to cpu_physical_memory_sync_dirty_bitmap() this function returns - * the number of dirty pages in @bitmap passed as argument. On the other hand, - * cpu_physical_memory_sync_dirty_bitmap() returns newly dirtied pages that - * weren't set in the global migration bitmap. - */ -static inline -uint64_t cpu_physical_memory_set_dirty_lebitmap(unsigned long *bitmap, - ram_addr_t start, - ram_addr_t pages) -{ - unsigned long i, j; - unsigned long page_number, c, nbits; - hwaddr addr; - ram_addr_t ram_addr; - uint64_t num_dirty = 0; - unsigned long len = (pages + HOST_LONG_BITS - 1) / HOST_LONG_BITS; - unsigned long hpratio = qemu_real_host_page_size() / TARGET_PAGE_SIZE; - unsigned long page = BIT_WORD(start >> TARGET_PAGE_BITS); - - /* start address is aligned at the start of a word? */ - if ((((page * BITS_PER_LONG) << TARGET_PAGE_BITS) == start) && - (hpratio == 1)) { - unsigned long **blocks[DIRTY_MEMORY_NUM]; - unsigned long idx; - unsigned long offset; - long k; - long nr = BITS_TO_LONGS(pages); - - idx = (start >> TARGET_PAGE_BITS) / DIRTY_MEMORY_BLOCK_SIZE; - offset = BIT_WORD((start >> TARGET_PAGE_BITS) % - DIRTY_MEMORY_BLOCK_SIZE); - - WITH_RCU_READ_LOCK_GUARD() { - for (i = 0; i < DIRTY_MEMORY_NUM; i++) { - blocks[i] = - qatomic_rcu_read(&ram_list.dirty_memory[i])->blocks; - } - - for (k = 0; k < nr; k++) { - if (bitmap[k]) { - unsigned long temp = leul_to_cpu(bitmap[k]); - - nbits = ctpopl(temp); - qatomic_or(&blocks[DIRTY_MEMORY_VGA][idx][offset], temp); - - if (global_dirty_tracking) { - qatomic_or( - &blocks[DIRTY_MEMORY_MIGRATION][idx][offset], - temp); - if (unlikely( - global_dirty_tracking & GLOBAL_DIRTY_DIRTY_RATE)) { - total_dirty_pages += nbits; - } - } - - num_dirty += nbits; - - if (tcg_enabled()) { - qatomic_or(&blocks[DIRTY_MEMORY_CODE][idx][offset], - temp); - } - } - - if (++offset >= BITS_TO_LONGS(DIRTY_MEMORY_BLOCK_SIZE)) { - offset = 0; - idx++; - } - } - } - - if (xen_enabled()) { - xen_hvm_modified_memory(start, pages << TARGET_PAGE_BITS); - } - } else { - uint8_t clients = tcg_enabled() ? DIRTY_CLIENTS_ALL : DIRTY_CLIENTS_NOCODE; - - if (!global_dirty_tracking) { - clients &= ~(1 << DIRTY_MEMORY_MIGRATION); - } - - /* - * bitmap-traveling is faster than memory-traveling (for addr...) - * especially when most of the memory is not dirty. - */ - for (i = 0; i < len; i++) { - if (bitmap[i] != 0) { - c = leul_to_cpu(bitmap[i]); - nbits = ctpopl(c); - if (unlikely(global_dirty_tracking & GLOBAL_DIRTY_DIRTY_RATE)) { - total_dirty_pages += nbits; - } - num_dirty += nbits; - do { - j = ctzl(c); - c &= ~(1ul << j); - page_number = (i * HOST_LONG_BITS + j) * hpratio; - addr = page_number * TARGET_PAGE_SIZE; - ram_addr = start + addr; - cpu_physical_memory_set_dirty_range(ram_addr, - TARGET_PAGE_SIZE * hpratio, clients); - } while (c != 0); - } - } - } - - return num_dirty; -} -#endif /* not _WIN32 */ - -static inline void cpu_physical_memory_dirty_bits_cleared(ram_addr_t start, - ram_addr_t length) -{ - if (tcg_enabled()) { - tlb_reset_dirty_range_all(start, length); - } - -} -bool cpu_physical_memory_test_and_clear_dirty(ram_addr_t start, - ram_addr_t length, - unsigned client); - -DirtyBitmapSnapshot *cpu_physical_memory_snapshot_and_clear_dirty - (MemoryRegion *mr, hwaddr offset, hwaddr length, unsigned client); - -bool cpu_physical_memory_snapshot_get_dirty(DirtyBitmapSnapshot *snap, - ram_addr_t start, - ram_addr_t length); - -static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start, - ram_addr_t length) -{ - cpu_physical_memory_test_and_clear_dirty(start, length, DIRTY_MEMORY_MIGRATION); - cpu_physical_memory_test_and_clear_dirty(start, length, DIRTY_MEMORY_VGA); - cpu_physical_memory_test_and_clear_dirty(start, length, DIRTY_MEMORY_CODE); -} - - -/* Called with RCU critical section */ -static inline -uint64_t cpu_physical_memory_sync_dirty_bitmap(RAMBlock *rb, - ram_addr_t start, - ram_addr_t length) -{ - ram_addr_t addr; - unsigned long word = BIT_WORD((start + rb->offset) >> TARGET_PAGE_BITS); - uint64_t num_dirty = 0; - unsigned long *dest = rb->bmap; - - /* start address and length is aligned at the start of a word? */ - if (((word * BITS_PER_LONG) << TARGET_PAGE_BITS) == - (start + rb->offset) && - !(length & ((BITS_PER_LONG << TARGET_PAGE_BITS) - 1))) { - int k; - int nr = BITS_TO_LONGS(length >> TARGET_PAGE_BITS); - unsigned long * const *src; - unsigned long idx = (word * BITS_PER_LONG) / DIRTY_MEMORY_BLOCK_SIZE; - unsigned long offset = BIT_WORD((word * BITS_PER_LONG) % - DIRTY_MEMORY_BLOCK_SIZE); - unsigned long page = BIT_WORD(start >> TARGET_PAGE_BITS); - - src = qatomic_rcu_read( - &ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION])->blocks; - - for (k = page; k < page + nr; k++) { - if (src[idx][offset]) { - unsigned long bits = qatomic_xchg(&src[idx][offset], 0); - unsigned long new_dirty; - new_dirty = ~dest[k]; - dest[k] |= bits; - new_dirty &= bits; - num_dirty += ctpopl(new_dirty); - } - - if (++offset >= BITS_TO_LONGS(DIRTY_MEMORY_BLOCK_SIZE)) { - offset = 0; - idx++; - } - } - if (num_dirty) { - cpu_physical_memory_dirty_bits_cleared(start, length); - } - - if (rb->clear_bmap) { - /* - * Postpone the dirty bitmap clear to the point before we - * really send the pages, also we will split the clear - * dirty procedure into smaller chunks. - */ - clear_bmap_set(rb, start >> TARGET_PAGE_BITS, - length >> TARGET_PAGE_BITS); - } else { - /* Slow path - still do that in a huge chunk */ - memory_region_clear_dirty_bitmap(rb->mr, start, length); - } - } else { - ram_addr_t offset = rb->offset; - - for (addr = 0; addr < length; addr += TARGET_PAGE_SIZE) { - if (cpu_physical_memory_test_and_clear_dirty( - start + addr + offset, - TARGET_PAGE_SIZE, - DIRTY_MEMORY_MIGRATION)) { - long k = (start + addr) >> TARGET_PAGE_BITS; - if (!test_and_set_bit(k, dest)) { - num_dirty++; - } - } - } - } - - return num_dirty; -} - #endif diff --git a/include/system/ramblock.h b/include/system/ramblock.h index d8a116b..76694fe 100644 --- a/include/system/ramblock.h +++ b/include/system/ramblock.h @@ -11,17 +11,16 @@ * */ -/* - * This header is for use by exec.c and memory.c ONLY. Do not include it. - * The functions declared here will be removed soon. - */ - #ifndef SYSTEM_RAMBLOCK_H #define SYSTEM_RAMBLOCK_H #include "exec/cpu-common.h" #include "qemu/rcu.h" #include "exec/ramlist.h" +#include "system/hostmem.h" + +#define TYPE_RAM_BLOCK_ATTRIBUTES "ram-block-attributes" +OBJECT_DECLARE_SIMPLE_TYPE(RamBlockAttributes, RAM_BLOCK_ATTRIBUTES) struct RAMBlock { struct rcu_head rcu; @@ -42,6 +41,7 @@ struct RAMBlock { int fd; uint64_t fd_offset; int guest_memfd; + RamBlockAttributes *attributes; size_t page_size; /* dirty bitmap used during migration */ unsigned long *bmap; @@ -91,4 +91,43 @@ struct RAMBlock { ram_addr_t postcopy_length; }; +struct RamBlockAttributes { + Object parent; + + RAMBlock *ram_block; + + /* 1-setting of the bitmap represents ram is populated (shared) */ + unsigned bitmap_size; + unsigned long *bitmap; + + QLIST_HEAD(, RamDiscardListener) rdl_list; +}; + +/* @offset: the offset within the RAMBlock */ +int ram_block_discard_range(RAMBlock *rb, uint64_t offset, size_t length); +/* @offset: the offset within the RAMBlock */ +int ram_block_discard_guest_memfd_range(RAMBlock *rb, uint64_t offset, + size_t length); + +RamBlockAttributes *ram_block_attributes_create(RAMBlock *ram_block); +void ram_block_attributes_destroy(RamBlockAttributes *attr); +int ram_block_attributes_state_change(RamBlockAttributes *attr, uint64_t offset, + uint64_t size, bool to_discard); + +/** + * ram_block_is_pmem: Whether the RAM block is of persistent memory + */ +bool ram_block_is_pmem(RAMBlock *rb); + +static inline bool offset_in_ramblock(RAMBlock *b, ram_addr_t offset) +{ + return b && b->host && (offset < b->used_length); +} + +static inline void *ramblock_ptr(RAMBlock *block, ram_addr_t offset) +{ + assert(offset_in_ramblock(block, offset)); + return (char *)block->host + offset; +} + #endif diff --git a/include/system/replay.h b/include/system/replay.h index 1c87c97..68f91bd 100644 --- a/include/system/replay.h +++ b/include/system/replay.h @@ -16,6 +16,7 @@ #include "qapi/qapi-types-run-state.h" #include "qapi/qapi-types-ui.h" #include "block/aio.h" +#include "qemu/audio.h" /* replay clock kinds */ enum ReplayClockKind { @@ -165,7 +166,7 @@ void replay_net_packet_event(ReplayNetState *rns, unsigned flags, /*! Saves/restores number of played samples of audio out operation. */ void replay_audio_out(size_t *played); /*! Saves/restores recorded samples of audio in operation. */ -void replay_audio_in(size_t *recorded, void *samples, size_t *wpos, size_t size); +void replay_audio_in(size_t *recorded, st_sample *samples, size_t *wpos, size_t size); /* VM state operations */ diff --git a/include/system/runstate.h b/include/system/runstate.h index fdd5c4a..929379a 100644 --- a/include/system/runstate.h +++ b/include/system/runstate.h @@ -14,11 +14,51 @@ void runstate_replay_enable(void); typedef void VMChangeStateHandler(void *opaque, bool running, RunState state); typedef int VMChangeStateHandlerWithRet(void *opaque, bool running, RunState state); +/** + * qemu_add_vm_change_state_handler: + * @cb: the callback to invoke + * @opaque: user data passed to the callback + * + * Register a callback function that is invoked when the vm starts or stops + * running. + * + * Returns: an entry to be freed using qemu_del_vm_change_state_handler() + */ VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb, void *opaque); +/** + * qemu_add_vm_change_state_handler_prio: + * @cb: the callback to invoke + * @opaque: user data passed to the callback + * @priority: low priorities execute first when the vm runs and the reverse is + * true when the vm stops + * + * Register a callback function that is invoked when the vm starts or stops + * running. + * + * Returns: an entry to be freed using qemu_del_vm_change_state_handler() + */ VMChangeStateEntry *qemu_add_vm_change_state_handler_prio( VMChangeStateHandler *cb, void *opaque, int priority); VMChangeStateEntry * +/** + * qemu_add_vm_change_state_handler_prio_full: + * @cb: the main callback to invoke + * @prepare_cb: a callback to invoke before the main callback + * @cb_ret: the main callback to invoke with return value + * @opaque: user data passed to the callbacks + * @priority: low priorities execute first when the vm runs and the reverse is + * true when the vm stops + * + * Register a main callback function and an optional prepare callback function + * that are invoked when the vm starts or stops running. The main callback and + * the prepare callback are called in two separate phases: First all prepare + * callbacks are called and only then all main callbacks are called. As its + * name suggests, the prepare callback can be used to do some preparatory work + * before invoking the main callback. + * + * Returns: an entry to be freed using qemu_del_vm_change_state_handler() + */ qemu_add_vm_change_state_handler_prio_full(VMChangeStateHandler *cb, VMChangeStateHandler *prepare_cb, VMChangeStateHandlerWithRet *cb_ret, @@ -107,6 +147,7 @@ void qemu_system_vmstop_request(RunState reason); void qemu_system_vmstop_request_prepare(void); bool qemu_vmstop_requested(RunState *r); ShutdownCause qemu_shutdown_requested_get(void); +bool qemu_force_shutdown_requested(void); ShutdownCause qemu_reset_requested_get(void); void qemu_system_killed(int signal, pid_t pid); void qemu_system_reset(ShutdownCause reason); diff --git a/include/system/spdm-socket.h b/include/system/spdm-socket.h index 5d8bd9a..00cb0e9 100644 --- a/include/system/spdm-socket.h +++ b/include/system/spdm-socket.h @@ -51,6 +51,35 @@ uint32_t spdm_socket_rsp(const int socket, uint32_t transport_type, void *rsp, uint32_t rsp_len); /** + * spdm_socket_rsp: Receive a message from an SPDM server + * @socket: socket returned from spdm_socket_connect() + * @transport_type: SPDM_SOCKET_TRANSPORT_TYPE_* macro + * @rsp: response buffer + * @rsp_len: response buffer length + * + * Receives a message from the SPDM server and returns the number of bytes + * received or 0 on failure. This can be used to receive a message from the SPDM + * server without sending anything first. + */ +uint32_t spdm_socket_receive(const int socket, uint32_t transport_type, + void *rsp, uint32_t rsp_len); + +/** + * spdm_socket_rsp: Sends a message to an SPDM server + * @socket: socket returned from spdm_socket_connect() + * @socket_cmd: socket command type (normal/if_recv/if_send etc...) + * @transport_type: SPDM_SOCKET_TRANSPORT_TYPE_* macro + * @req: request buffer + * @req_len: request buffer length + * + * Sends platform data to a SPDM server on socket, returns true on success. + * The response from the server must then be fetched by using + * spdm_socket_receive(). + */ +bool spdm_socket_send(const int socket, uint32_t socket_cmd, + uint32_t transport_type, void *req, uint32_t req_len); + +/** * spdm_socket_close: send a shutdown command to the server * @socket: socket returned from spdm_socket_connect() * @transport_type: SPDM_SOCKET_TRANSPORT_TYPE_* macro @@ -59,16 +88,46 @@ uint32_t spdm_socket_rsp(const int socket, uint32_t transport_type, */ void spdm_socket_close(const int socket, uint32_t transport_type); +/* + * Defines the transport encoding for SPDM, this information shall be passed + * down to the SPDM server, when conforming to the SPDM over Storage standard + * as defined by DSP0286. + */ +typedef struct { + uint8_t security_protocol; /* Must be 0xE8 for SPDM Commands + as per SCSI Primary Commands 5 */ + uint16_t security_protocol_specific; /* Bit[7:2] SPDM Operation + Bit[0:1] Connection ID + per DSP0286 1.0: Section 7.2 */ + uint32_t length; /* Length of the SPDM Message*/ +} QEMU_PACKED StorageSpdmTransportHeader; + #define SPDM_SOCKET_COMMAND_NORMAL 0x0001 +#define SPDM_SOCKET_STORAGE_CMD_IF_SEND 0x0002 +#define SPDM_SOCKET_STORAGE_CMD_IF_RECV 0x0003 +#define SOCKET_SPDM_STORAGE_ACK_STATUS 0x0004 #define SPDM_SOCKET_COMMAND_OOB_ENCAP_KEY_UPDATE 0x8001 #define SPDM_SOCKET_COMMAND_CONTINUE 0xFFFD #define SPDM_SOCKET_COMMAND_SHUTDOWN 0xFFFE #define SPDM_SOCKET_COMMAND_UNKOWN 0xFFFF #define SPDM_SOCKET_COMMAND_TEST 0xDEAD -#define SPDM_SOCKET_TRANSPORT_TYPE_MCTP 0x01 -#define SPDM_SOCKET_TRANSPORT_TYPE_PCI_DOE 0x02 - #define SPDM_SOCKET_MAX_MESSAGE_BUFFER_SIZE 0x1200 +#define SPDM_SOCKET_MAX_MSG_STATUS_LEN 0x02 + +typedef enum SpdmTransportType { + SPDM_SOCKET_TRANSPORT_TYPE_UNSPEC = 0, + SPDM_SOCKET_TRANSPORT_TYPE_MCTP, + SPDM_SOCKET_TRANSPORT_TYPE_PCI_DOE, + SPDM_SOCKET_TRANSPORT_TYPE_SCSI, + SPDM_SOCKET_TRANSPORT_TYPE_NVME, + SPDM_SOCKET_TRANSPORT_TYPE_MAX +} SpdmTransportType; + +extern const PropertyInfo qdev_prop_spdm_trans; + +#define DEFINE_PROP_SPDM_TRANS(_name, _state, _field, _default) \ + DEFINE_PROP_UNSIGNED(_name, _state, _field, _default, \ + qdev_prop_spdm_trans, SpdmTransportType) #endif diff --git a/include/system/system.h b/include/system/system.h index a7effe7..03a2d0e 100644 --- a/include/system/system.h +++ b/include/system/system.h @@ -42,7 +42,6 @@ extern int graphic_height; extern int graphic_depth; extern int display_opengl; extern const char *keyboard_layout; -extern int old_param; extern uint8_t *boot_splash_filedata; extern bool enable_cpu_pm; extern QEMUClockType rtc_clock; diff --git a/include/system/vhost-user-backend.h b/include/system/vhost-user-backend.h index 5634ebd..3184c8e 100644 --- a/include/system/vhost-user-backend.h +++ b/include/system/vhost-user-backend.h @@ -32,7 +32,7 @@ struct VhostUserBackend { Object parent; char *chr_name; - CharBackend chr; + CharFrontend chr; VhostUserState vhost_user; struct vhost_dev dev; VirtIODevice *vdev; diff --git a/include/system/whpx.h b/include/system/whpx.h index 00ff409..00f6a3e 100644 --- a/include/system/whpx.h +++ b/include/system/whpx.h @@ -16,19 +16,20 @@ #define QEMU_WHPX_H #ifdef COMPILING_PER_TARGET +# ifdef CONFIG_WHPX +# define CONFIG_WHPX_IS_POSSIBLE +# endif /* !CONFIG_WHPX */ +#else +# define CONFIG_WHPX_IS_POSSIBLE +#endif /* COMPILING_PER_TARGET */ -#ifdef CONFIG_WHPX - -int whpx_enabled(void); +#ifdef CONFIG_WHPX_IS_POSSIBLE +extern bool whpx_allowed; +#define whpx_enabled() (whpx_allowed) bool whpx_apic_in_platform(void); - -#else /* CONFIG_WHPX */ - -#define whpx_enabled() (0) +#else /* !CONFIG_WHPX_IS_POSSIBLE */ +#define whpx_enabled() 0 #define whpx_apic_in_platform() (0) - -#endif /* CONFIG_WHPX */ - -#endif /* COMPILING_PER_TARGET */ +#endif /* !CONFIG_WHPX_IS_POSSIBLE */ #endif /* QEMU_WHPX_H */ diff --git a/include/tcg/helper-info.h b/include/tcg/helper-info.h index 909fe73..49a27e4 100644 --- a/include/tcg/helper-info.h +++ b/include/tcg/helper-info.h @@ -10,7 +10,19 @@ #define TCG_HELPER_INFO_H #ifdef CONFIG_TCG_INTERPRETER +/* + * MacOSX 15 uses an old version of libffi which contains + * #if FFI_GO_CLOSURES + * but does not define that in <ffitarget.h>, included from <ffi.h>. + * This was fixed upstream with + * https://github.com/libffi/libffi/commit/c23e9a1c + * We don't care about go closures one way or the other; + * just suppress the warning. + */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wundef" #include <ffi.h> +#pragma GCC diagnostic pop #endif #include "tcg-target-reg-bits.h" diff --git a/include/tcg/tcg-op-common.h b/include/tcg/tcg-op-common.h index e1071ad..f752ef4 100644 --- a/include/tcg/tcg-op-common.h +++ b/include/tcg/tcg-op-common.h @@ -344,6 +344,8 @@ void tcg_gen_atomic_xchg_i32_chk(TCGv_i32, TCGTemp *, TCGv_i32, TCGArg, MemOp, TCGType); void tcg_gen_atomic_xchg_i64_chk(TCGv_i64, TCGTemp *, TCGv_i64, TCGArg, MemOp, TCGType); +void tcg_gen_atomic_xchg_i128_chk(TCGv_i128, TCGTemp *, TCGv_i128, + TCGArg, MemOp, TCGType); void tcg_gen_atomic_fetch_add_i32_chk(TCGv_i32, TCGTemp *, TCGv_i32, TCGArg, MemOp, TCGType); @@ -411,6 +413,11 @@ void tcg_gen_atomic_umax_fetch_i32_chk(TCGv_i32, TCGTemp *, TCGv_i32, void tcg_gen_atomic_umax_fetch_i64_chk(TCGv_i64, TCGTemp *, TCGv_i64, TCGArg, MemOp, TCGType); +void tcg_gen_atomic_fetch_and_i128_chk(TCGv_i128, TCGTemp *, TCGv_i128, + TCGArg, MemOp, TCGType); +void tcg_gen_atomic_fetch_or_i128_chk(TCGv_i128, TCGTemp *, TCGv_i128, + TCGArg, MemOp, TCGType); + /* Vector ops */ void tcg_gen_mov_vec(TCGv_vec, TCGv_vec); diff --git a/include/tcg/tcg-op-gvec-common.h b/include/tcg/tcg-op-gvec-common.h index 65553f5..ea0c87f 100644 --- a/include/tcg/tcg-op-gvec-common.h +++ b/include/tcg/tcg-op-gvec-common.h @@ -227,25 +227,66 @@ typedef struct { bool prefer_i64; } GVecGen4i; +/* Expand (dbase+dofs) = op(abase+aofs), length @oprsz, clearing to @maxsz. */ +void tcg_gen_gvec_2_var(TCGv_ptr dbase, uint32_t dofs, + TCGv_ptr abase, uint32_t aofs, + uint32_t oprsz, uint32_t maxsz, const GVecGen2 *op); +/* Similarly, expand (env+dofs) = op(env+aofs). */ void tcg_gen_gvec_2(uint32_t dofs, uint32_t aofs, - uint32_t oprsz, uint32_t maxsz, const GVecGen2 *); + uint32_t oprsz, uint32_t maxsz, const GVecGen2 *op); +/* Similarly, expand (env+dofs) = op(env+aofs, c). */ void tcg_gen_gvec_2i(uint32_t dofs, uint32_t aofs, uint32_t oprsz, - uint32_t maxsz, int64_t c, const GVecGen2i *); + uint32_t maxsz, int64_t c, const GVecGen2i *op); +/* Similarly, expand (env+dofs) = op(env+aofs, s). */ void tcg_gen_gvec_2s(uint32_t dofs, uint32_t aofs, uint32_t oprsz, - uint32_t maxsz, TCGv_i64 c, const GVecGen2s *); + uint32_t maxsz, TCGv_i64 c, const GVecGen2s *op); + +/* + * Expand (dbase+dofs) = op(abase+aofs, bbase+bofs), + * length @oprsz, clearing to @maxsz. + */ +void tcg_gen_gvec_3_var(TCGv_ptr dbase, uint32_t dofs, + TCGv_ptr abase, uint32_t aofs, + TCGv_ptr bbase, uint32_t bofs, + uint32_t oprsz, uint32_t maxsz, const GVecGen3 *op); +/* Similarly, expand (env+dofs) = op(env+aofs, env+bofs). */ void tcg_gen_gvec_3(uint32_t dofs, uint32_t aofs, uint32_t bofs, - uint32_t oprsz, uint32_t maxsz, const GVecGen3 *); + uint32_t oprsz, uint32_t maxsz, const GVecGen3 *op); + +/* + * Depending on op->load_dest and op->write_aofs, expand + * (env+dofs) = op(env+aofs, env+bofs, c) + * or + * (env+dofs) = op(env+dofs, env+aofs, env+bofs, c) + * or + * (env+dofs), (env+aofs) = op(env+aofs, env+bofs, c) + * or + * (env+dofs), (env+aofs) = op(env+dofs, env+aofs, env+bofs, c) + */ void tcg_gen_gvec_3i(uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t oprsz, uint32_t maxsz, int64_t c, - const GVecGen3i *); + const GVecGen3i *op); + +/* + * Depending on op->write_aofs, expand + * (env+dofs) = op(env+aofs, env+bofs, env+cofs) + * or + * (env+dofs), (env+aofs) = op(env+aofs, env+bofs, env+cofs) + */ void tcg_gen_gvec_4(uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t cofs, uint32_t oprsz, uint32_t maxsz, const GVecGen4 *); + +/* Expand (env+dofs) = op(env+aofs, env+bofs, env+cofs, c). */ void tcg_gen_gvec_4i(uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t cofs, uint32_t oprsz, uint32_t maxsz, int64_t c, const GVecGen4i *); /* Expand a specific vector operation. */ +void tcg_gen_gvec_mov_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs, + TCGv_ptr abase, uint32_t aofs, + uint32_t oprsz, uint32_t maxsz); + void tcg_gen_gvec_mov(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t oprsz, uint32_t maxsz); void tcg_gen_gvec_not(unsigned vece, uint32_t dofs, uint32_t aofs, @@ -255,6 +296,15 @@ void tcg_gen_gvec_neg(unsigned vece, uint32_t dofs, uint32_t aofs, void tcg_gen_gvec_abs(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t oprsz, uint32_t maxsz); +void tcg_gen_gvec_add_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs, + TCGv_ptr abase, uint32_t aofs, + TCGv_ptr bbase, uint32_t bofs, + uint32_t oprsz, uint32_t maxsz); +void tcg_gen_gvec_sub_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs, + TCGv_ptr abase, uint32_t aofs, + TCGv_ptr bbase, uint32_t bofs, + uint32_t oprsz, uint32_t maxsz); + void tcg_gen_gvec_add(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t oprsz, uint32_t maxsz); void tcg_gen_gvec_sub(unsigned vece, uint32_t dofs, uint32_t aofs, @@ -336,6 +386,9 @@ void tcg_gen_gvec_dup_i32(unsigned vece, uint32_t dofs, uint32_t s, void tcg_gen_gvec_dup_i64(unsigned vece, uint32_t dofs, uint32_t s, uint32_t m, TCGv_i64); +void tcg_gen_gvec_dup_imm_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs, + uint32_t oprsz, uint32_t maxsz, uint64_t imm); + void tcg_gen_gvec_shli(unsigned vece, uint32_t dofs, uint32_t aofs, int64_t shift, uint32_t oprsz, uint32_t maxsz); void tcg_gen_gvec_shri(unsigned vece, uint32_t dofs, uint32_t aofs, diff --git a/include/tcg/tcg-op.h b/include/tcg/tcg-op.h index c912578..232733c 100644 --- a/include/tcg/tcg-op.h +++ b/include/tcg/tcg-op.h @@ -134,13 +134,16 @@ DEF_ATOMIC3(tcg_gen_nonatomic_cmpxchg, i128) DEF_ATOMIC2(tcg_gen_atomic_xchg, i32) DEF_ATOMIC2(tcg_gen_atomic_xchg, i64) +DEF_ATOMIC2(tcg_gen_atomic_xchg, i128) DEF_ATOMIC2(tcg_gen_atomic_fetch_add, i32) DEF_ATOMIC2(tcg_gen_atomic_fetch_add, i64) DEF_ATOMIC2(tcg_gen_atomic_fetch_and, i32) DEF_ATOMIC2(tcg_gen_atomic_fetch_and, i64) +DEF_ATOMIC2(tcg_gen_atomic_fetch_and, i128) DEF_ATOMIC2(tcg_gen_atomic_fetch_or, i32) DEF_ATOMIC2(tcg_gen_atomic_fetch_or, i64) +DEF_ATOMIC2(tcg_gen_atomic_fetch_or, i128) DEF_ATOMIC2(tcg_gen_atomic_fetch_xor, i32) DEF_ATOMIC2(tcg_gen_atomic_fetch_xor, i64) DEF_ATOMIC2(tcg_gen_atomic_fetch_smin, i32) diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h index 3fa5a7a..a6d9aa5 100644 --- a/include/tcg/tcg.h +++ b/include/tcg/tcg.h @@ -357,7 +357,7 @@ static inline TCGRegSet output_pref(const TCGOp *op, unsigned i) } struct TCGContext { - uint8_t *pool_cur, *pool_end; + uintptr_t pool_cur, pool_end; TCGPool *pool_first, *pool_current, *pool_first_large; int nb_labels; int nb_globals; @@ -365,10 +365,6 @@ struct TCGContext { int nb_indirects; int nb_ops; TCGType addr_type; /* TCG_TYPE_I32 or TCG_TYPE_I64 */ - - int page_mask; - uint8_t page_bits; - uint8_t tlb_dyn_max_bits; TCGBar guest_mo; TCGRegSet reserved_regs; @@ -710,7 +706,7 @@ size_t tcg_nb_tbs(void); static inline void *tcg_malloc(int size) { TCGContext *s = tcg_ctx; - uint8_t *ptr, *ptr_end; + uintptr_t ptr, ptr_end; /* ??? This is a weak placeholder for minimum malloc alignment. */ size = QEMU_ALIGN_UP(size, 8); @@ -721,7 +717,7 @@ static inline void *tcg_malloc(int size) return tcg_malloc_internal(tcg_ctx, size); } else { s->pool_cur = ptr_end; - return ptr; + return (void *)ptr; } } @@ -1009,5 +1005,7 @@ static inline const TCGOpcode *tcg_swap_vecop_list(const TCGOpcode *n) bool tcg_can_emit_vecop_list(const TCGOpcode *, TCGType, unsigned); void tcg_dump_ops(TCGContext *s, FILE *f, bool have_prefs); +/* tcg_dump_stats: Append TCG statistics to @buf */ +void tcg_dump_stats(GString *buf); #endif /* TCG_H */ diff --git a/include/ui/clipboard.h b/include/ui/clipboard.h index ab6acdb..62a96ce 100644 --- a/include/ui/clipboard.h +++ b/include/ui/clipboard.h @@ -2,6 +2,7 @@ #define QEMU_CLIPBOARD_H #include "qemu/notify.h" +#include "migration/vmstate.h" /** * DOC: Introduction @@ -25,6 +26,9 @@ typedef enum QemuClipboardSelection QemuClipboardSelection; typedef struct QemuClipboardPeer QemuClipboardPeer; typedef struct QemuClipboardNotify QemuClipboardNotify; typedef struct QemuClipboardInfo QemuClipboardInfo; +typedef struct QemuClipboardContent QemuClipboardContent; + +extern const VMStateDescription vmstate_cbinfo; /** * enum QemuClipboardType @@ -97,6 +101,24 @@ struct QemuClipboardNotify { }; }; + +/** + * struct QemuClipboardContent + * + * @available: whether the data is available + * @requested: whether the data was requested + * @size: the size of the @data + * @data: the clipboard data + * + * Clipboard content. + */ +struct QemuClipboardContent { + bool available; + bool requested; + uint32_t size; + void *data; +}; + /** * struct QemuClipboardInfo * @@ -112,15 +134,10 @@ struct QemuClipboardNotify { struct QemuClipboardInfo { uint32_t refcount; QemuClipboardPeer *owner; - QemuClipboardSelection selection; + int selection; /* QemuClipboardSelection */ bool has_serial; uint32_t serial; - struct { - bool available; - bool requested; - size_t size; - void *data; - } types[QEMU_CLIPBOARD_TYPE__COUNT]; + QemuClipboardContent types[QEMU_CLIPBOARD_TYPE__COUNT]; }; /** diff --git a/include/ui/console.h b/include/ui/console.h index 46b3128..98feaa5 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -422,6 +422,9 @@ bool console_gl_check_format(DisplayChangeListener *dcl, pixman_format_code_t format); void surface_gl_create_texture(QemuGLShader *gls, DisplaySurface *surface); +bool surface_gl_create_texture_from_fd(DisplaySurface *surface, + int fd, GLuint *texture, + GLuint *mem_obj); void surface_gl_update_texture(QemuGLShader *gls, DisplaySurface *surface, int x, int y, int w, int h); diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h index fb80e15..acf993f 100644 --- a/include/ui/egl-helpers.h +++ b/include/ui/egl-helpers.h @@ -17,6 +17,8 @@ extern bool qemu_egl_angle_d3d; typedef struct egl_fb { int width; int height; + int x; + int y; GLuint texture; GLuint framebuffer; bool delete_texture; @@ -26,7 +28,7 @@ typedef struct egl_fb { #define EGL_FB_INIT { 0, } void egl_fb_destroy(egl_fb *fb); -void egl_fb_setup_default(egl_fb *fb, int width, int height); +void egl_fb_setup_default(egl_fb *fb, int width, int height, int x, int y); void egl_fb_setup_for_tex(egl_fb *fb, int width, int height, GLuint texture, bool delete); void egl_fb_setup_new_tex(egl_fb *fb, int width, int height); diff --git a/include/ui/gtk.h b/include/ui/gtk.h index aa3d637..3e6ce3c 100644 --- a/include/ui/gtk.h +++ b/include/ui/gtk.h @@ -41,6 +41,7 @@ typedef struct VirtualGfxConsole { DisplaySurface *ds; pixman_image_t *convert; cairo_surface_t *surface; + double preferred_scale; double scale_x; double scale_y; #if defined(CONFIG_OPENGL) @@ -140,6 +141,7 @@ struct GtkDisplayState { GdkCursor *null_cursor; Notifier mouse_mode_notifier; gboolean free_scale; + gboolean keep_aspect_ratio; bool external_pause_update; @@ -224,4 +226,6 @@ int gd_gl_area_make_current(DisplayGLCtx *dgc, /* gtk-clipboard.c */ void gd_clipboard_init(GtkDisplayState *gd); +void gd_update_scale(VirtualConsole *vc, int ww, int wh, int fbw, int fbh); + #endif /* UI_GTK_H */ diff --git a/include/ui/qemu-pixman.h b/include/ui/qemu-pixman.h index 193bc04..2ca0ed7 100644 --- a/include/ui/qemu-pixman.h +++ b/include/ui/qemu-pixman.h @@ -75,12 +75,12 @@ PixelFormat qemu_pixelformat_from_pixman(pixman_format_code_t format); pixman_format_code_t qemu_default_pixman_format(int bpp, bool native_endian); pixman_format_code_t qemu_drm_format_to_pixman(uint32_t drm_format); uint32_t qemu_pixman_to_drm_format(pixman_format_code_t pixman); -int qemu_pixman_get_type(int rshift, int gshift, int bshift); +int qemu_pixman_get_type(int rshift, int gshift, int bshift, int endian); bool qemu_pixman_check_format(DisplayChangeListener *dcl, pixman_format_code_t format); #ifdef CONFIG_PIXMAN -pixman_format_code_t qemu_pixman_get_format(PixelFormat *pf); +pixman_format_code_t qemu_pixman_get_format(PixelFormat *pf, int endian); pixman_image_t *qemu_pixman_linebuf_create(pixman_format_code_t format, int width); void qemu_pixman_linebuf_fill(pixman_image_t *linebuf, pixman_image_t *fb, diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h index e1a9b36..690ece7 100644 --- a/include/ui/spice-display.h +++ b/include/ui/spice-display.h @@ -132,6 +132,9 @@ struct SimpleSpiceDisplay { egl_fb guest_fb; egl_fb blit_fb; egl_fb cursor_fb; + bool backing_y_0_top; + bool blit_scanout_texture; + bool new_scanout_texture; bool have_hot; #endif }; @@ -151,6 +154,8 @@ struct SimpleSpiceCursor { }; extern bool spice_opengl; +extern bool spice_remote_client; +extern int spice_max_refresh_rate; int qemu_spice_rect_is_empty(const QXLRect* r); void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r); diff --git a/include/ui/surface.h b/include/ui/surface.h index f16f7be..006b198 100644 --- a/include/ui/surface.h +++ b/include/ui/surface.h @@ -22,6 +22,7 @@ typedef struct DisplaySurface { GLenum glformat; GLenum gltype; GLuint texture; + GLuint mem_obj; #endif qemu_pixman_shareable share_handle; uint32_t share_handle_offset; diff --git a/include/user/abitypes.h b/include/user/abitypes.h index 7528124..be7a876 100644 --- a/include/user/abitypes.h +++ b/include/user/abitypes.h @@ -6,7 +6,6 @@ #endif #include "exec/cpu-defs.h" -#include "exec/tswap.h" #include "user/tswap-target.h" #ifdef TARGET_ABI32 diff --git a/include/user/cpu_loop.h b/include/user/cpu_loop.h index ad8a1d7..346e37e 100644 --- a/include/user/cpu_loop.h +++ b/include/user/cpu_loop.h @@ -81,8 +81,4 @@ void target_exception_dump(CPUArchState *env, const char *fmt, int code); #define EXCP_DUMP(env, fmt, code) \ target_exception_dump(env, fmt, code) -typedef struct target_pt_regs target_pt_regs; - -void target_cpu_copy_regs(CPUArchState *env, target_pt_regs *regs); - #endif diff --git a/include/user/page-protection.h b/include/user/page-protection.h index 4bde664..41b23e7 100644 --- a/include/user/page-protection.h +++ b/include/user/page-protection.h @@ -23,14 +23,19 @@ int page_get_flags(vaddr address); * page_set_flags: * @start: first byte of range * @last: last byte of range - * @flags: flags to set + * @set_flags: flags to set + * @clr_flags: flags to clear * Context: holding mmap lock * * Modify the flags of a page and invalidate the code if necessary. * The flag PAGE_WRITE_ORG is positioned automatically depending * on PAGE_WRITE. The mmap_lock should already be held. + * + * For each page, flags = (flags & ~clr_flags) | set_flags. + * If clr_flags includes PAGE_VALID, this indicates a new mapping + * and page_reset_target_data will be called as well. */ -void page_set_flags(vaddr start, vaddr last, int flags); +void page_set_flags(vaddr start, vaddr last, int set_flags, int clr_flags); void page_reset_target_data(vaddr start, vaddr last); |
