target_mask_filter() intersects any other mask with
target_mask_selected(). QEMU_ARCH_ALL stays unchanged. Tools
cannot select a target, so a mask other than QEMU_ARCH_ALL aborts
registration. System mode keeps the mask until a target is
selected, then keeps only that target's bit. Registration returns
NULL when the filtered mask is empty.

Signed-off-by: Yonggang Luo <[email protected]>
---
 qom/object.c | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/qom/object.c b/qom/object.c
index b7e1924e81..c224263112 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -16,6 +16,8 @@
 #include "qom/object.h"
 #include "qom/object_interfaces.h"
 #include "qemu/cutils.h"
+#include "qemu/base-arch-defs.h"
+#include "qemu/target-info.h"
 #include "qemu/memalign.h"
 #include "qapi/visitor.h"
 #include "qapi/string-input-visitor.h"
@@ -88,6 +90,29 @@ static GHashTable *type_table;
 
 static bool enumerating_types;
 
+/**
+ * target_mask_filter:
+ * @mask: QEMU_ARCH_* mask to filter.
+ *
+ * QEMU_ARCH_ALL is unchanged for tools, user mode, and system mode.
+ *
+ * Tools return 0 from target_mask_selected() and cannot select a
+ * target, so any other mask aborts registration.
+ *
+ * Before system mode selects a target, target_mask_selected() is
+ * QEMU_ARCH_ALL and @mask is unchanged.
+ *
+ * When a target is selected, any other mask is intersected with
+ * QEMU_ARCH_BIT() of that target. User mode always has a target.
+ */
+static uint64_t target_mask_filter(uint64_t mask)
+{
+    if (mask == QEMU_ARCH_ALL) {
+        return mask;
+    }
+    return mask & target_mask_selected();
+}
+
 static void type_table_add(TypeImpl *ti)
 {
     assert(!enumerating_types);
@@ -174,6 +199,19 @@ static TypeImpl *type_register_internal(const TypeInfo 
*info, uint64_t targets)
         return NULL;
     }
 
+    /* Tools cannot select a target, so targets must be QEMU_ARCH_ALL. */
+    if (target_mask_selected() == 0 && targets != QEMU_ARCH_ALL) {
+        fprintf(stderr,
+                "Registering '%s' with targets other than QEMU_ARCH_ALL "
+                "in tools\n", info->name);
+        abort();
+    }
+
+    targets = target_mask_filter(targets);
+    if (!targets) {
+        return NULL;
+    }
+
     ti = type_new(info, targets);
 
     type_table_add(ti);
-- 
2.55.0.windows.3


Reply via email to