[PATCH v2 1/2] qom/object: add available_if field to TypeInfo
Pierrick Bouvier <[email protected]>
| Newsgroups | org.nongnu.qemu-devel |
|---|---|
| Message-ID | <[email protected]> |
With the single-binary, we start mixing types for different targets, that may or may not be available for current one. Previously, we implemented an approach based on interfaces, but it proved to be too limited. It requires duplication between machines/cpus/devices, and does not handle specific cases where a type should be available based on a target configuration (Kconfig). To solve this, we add a new field, available_if, to TypeInfo. It is an array containing a list of requirements for type to be available. For now, we have only targets as requirements, but later we'll add specific target config entries also. We also add a TARGET_REQS macro, to declare a list of requirements. For sanity sake, we don't use a complex variadic macro prefixing each parameter. It requires a lot of macro boilerplate in C, and prevent readers to jump easily to definition for each parameter. Signed-off-by: Pierrick Bouvier <[email protected]> --- include/qemu/target-info.h | 11 +++++++++++ include/qom/object.h | 5 +++++ qom/object.c | 10 ++++++++++ rust/qom/src/qom.rs | 1 + stubs/meson.build | 1 + stubs/target-info.c | 11 +++++++++++ target-info.c | 13 +++++++++++++ 7 files changed, 52 insertions(+) create mode 100644 stubs/target-info.c diff --git a/include/qemu/target-info.h b/include/qemu/target-info.h index 6c5b714288e..6379e65bbcf 100644 --- a/include/qemu/target-info.h +++ b/include/qemu/target-info.h @@ -50,6 +50,17 @@ const char *target_cpu_type(void); */ bool target_big_endian(void); +typedef enum TargetReq { + /* 0 is reserved for end of array */ + TARGET_REQ_BASE_ARM = 1, + TARGET_REQ_AARCH64, + TARGET_REQ_ARM, +} TargetReq; + +#define TARGET_REQS(...) (const TargetReq[]){__VA_ARGS__, 0} + +bool target_requirement(TargetReq Req); + /** * target_base_arm: * diff --git a/include/qom/object.h b/include/qom/object.h index 11b1c9d2dc8..75bac929c14 100644 --- a/include/qom/object.h +++ b/include/qom/object.h @@ -24,6 +24,7 @@ typedef struct TypeInfo TypeInfo; typedef struct InterfaceClass InterfaceClass; typedef struct InterfaceInfo InterfaceInfo; +typedef enum TargetReq TargetReq; #define TYPE_OBJECT "object" #define TYPE_CONTAINER "container" @@ -469,6 +470,9 @@ struct Object * @class_data: Data to pass to the @class_init, * @class_base_init. This can be useful when building dynamic * classes. + * @available_if: List of requirements for type to be available. This + * should point to a static array that's terminated with a zero filled + * element. * @interfaces: The list of interfaces associated with this type. This * should point to a static array that's terminated with a zero filled * element. @@ -491,6 +495,7 @@ struct TypeInfo void (*class_base_init)(ObjectClass *klass, const void *data); const void *class_data; + const TargetReq *available_if; const InterfaceInfo *interfaces; }; diff --git a/qom/object.c b/qom/object.c index 47977b1f440..02c5cd9d7b8 100644 --- a/qom/object.c +++ b/qom/object.c @@ -17,6 +17,7 @@ #include "qom/object_interfaces.h" #include "qemu/cutils.h" #include "qemu/memalign.h" +#include "qemu/target-info.h" #include "qapi/visitor.h" #include "qapi/string-input-visitor.h" #include "qapi/string-output-visitor.h" @@ -172,6 +173,15 @@ static TypeImpl *type_register_internal(const TypeInfo *info) TypeImpl *type_register_static(const TypeInfo *info) { assert(info->parent); + + if (info->available_if) { + for (const TargetReq *req = info->available_if; *req; ++req) { + if (!target_requirement(*req)) { + return NULL; + } + } + } + return type_register_internal(info); } diff --git a/rust/qom/src/qom.rs b/rust/qom/src/qom.rs index cc00ddcfc98..f065df57542 100644 --- a/rust/qom/src/qom.rs +++ b/rust/qom/src/qom.rs @@ -691,6 +691,7 @@ pub trait ObjectImpl: ObjectType + IsA<Object> { class_init: Some(rust_class_init::<Self>), class_base_init: Self::CLASS_BASE_INIT, class_data: core::ptr::null(), + available_if: core::ptr::null(), interfaces: core::ptr::null(), }; diff --git a/stubs/meson.build b/stubs/meson.build index 3b2f2680b19..dee2bc5a1a2 100644 --- a/stubs/meson.build +++ b/stubs/meson.build @@ -8,6 +8,7 @@ stub_ss.add(files('iothread-lock.c')) stub_ss.add(files('is-daemonized.c')) stub_ss.add(files('monitor-core.c')) stub_ss.add(files('replay-mode.c')) +stub_ss.add(files('target-info.c')) stub_ss.add(files('trace-control.c')) if have_block diff --git a/stubs/target-info.c b/stubs/target-info.c new file mode 100644 index 00000000000..ab034e7a8d2 --- /dev/null +++ b/stubs/target-info.c @@ -0,0 +1,11 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/target-info.h" + +bool target_requirement(TargetReq req) +{ + return true; +} diff --git a/target-info.c b/target-info.c index 04c69c41f8a..a4ff24e021f 100644 --- a/target-info.c +++ b/target-info.c @@ -47,6 +47,19 @@ bool target_big_endian(void) return target_endian_mode() == ENDIAN_MODE_BIG; } +bool target_requirement(TargetReq req) +{ + switch (req) { + case TARGET_REQ_BASE_ARM: + return target_base_arm(); + case TARGET_REQ_AARCH64: + return target_aarch64(); + case TARGET_REQ_ARM: + return target_arm(); + } + g_assert_not_reached(); +} + bool target_base_arm(void) { switch (target_arch()) { -- 2.43.0