The combined qemu-system binary can select a registered target by
name, or stay on SYS_EMU_TARGET_NONE. A single-target binary does
not switch target.

The none entry is the same target-info-def.c stub as other targets,
compiled with TARGET_BASE_ARCH NONE. target/none/cpu.h supplies
ArchCPU for that stub, and cpu-param.h sets
TARGET_VIRT_ADDR_SPACE_BITS. TYPE_NONE_CPU is NULL because there is
no none CPU QOM type.

type_register_internal() keeps types on the combined binary and
filters them with TypeInfo.is_available. A single-target binary
still omits types that cannot run.

Signed-off-by: Yonggang Luo <[email protected]>
---
 include/qemu/target-info-select.h | 24 +++++++++++++++++++++
 meson.build                       | 35 +++++++++++++++++++++++++++++++
 qom/object.c                      |  8 ++++++-
 stubs/meson.build                 |  1 +
 stubs/target-info-select.c        | 14 +++++++++++++
 system/target-info-select.c       | 26 +++++++++++++++++++++++
 target/none/cpu-param.h           |  7 +++++++
 target/none/cpu-qom.h             |  6 ++++++
 target/none/cpu.h                 | 18 ++++++++++++++++
 9 files changed, 138 insertions(+), 1 deletion(-)
 create mode 100644 include/qemu/target-info-select.h
 create mode 100644 stubs/target-info-select.c
 create mode 100644 system/target-info-select.c
 create mode 100644 target/none/cpu-param.h
 create mode 100644 target/none/cpu-qom.h
 create mode 100644 target/none/cpu.h

diff --git a/include/qemu/target-info-select.h 
b/include/qemu/target-info-select.h
new file mode 100644
index 00000000000..0659bb47567
--- /dev/null
+++ b/include/qemu/target-info-select.h
@@ -0,0 +1,24 @@
+#ifndef QEMU_TARGET_INFO_SELECT_H
+#define QEMU_TARGET_INFO_SELECT_H
+
+/**
+ * target_combined_binary:
+ *
+ * Returns: %true if this is the combined qemu-system binary.
+ */
+bool target_combined_binary(void);
+
+typedef struct Error Error;
+
+/**
+ * target_info_select_by_name:
+ * @name: target_name to select, or NULL
+ * @errp: error location
+ *
+ * Combined qemu-system only. NULL selects "none". Every name, including
+ * "none", is looked up in target_info_list(). The stub is a no-op on
+ * single-target binaries.
+ */
+void target_info_select_by_name(const char *name, Error **errp);
+
+#endif
diff --git a/meson.build b/meson.build
index 7ab5c7971a8..96f493cb746 100644
--- a/meson.build
+++ b/meson.build
@@ -4618,6 +4618,41 @@ if single_binary_available
   endforeach
   single_binary_objects += single_binary_target_info_objects
 
+  none_config_target_data = configuration_data()
+  none_config_target_data.set_quoted('TARGET_NAME', 'none')
+  none_config_target_data.set('TARGET_ARCH', 'NONE')
+  none_config_target_data.set('TARGET_BASE_ARCH', 'NONE')
+  none_config_target_data.set('TARGET_LONG_BITS', 64)
+  none_config_target_data.set('TARGET_BIG_ENDIAN', 0)
+  none_config_target_h = configure_file(output: 'none-config-target.h',
+                                        configuration: none_config_target_data)
+  none_config_devices_data = configuration_data()
+  foreach k, v : single_binary_config
+    if v == 'y'
+      none_config_devices_data.set(k, 1)
+    endif
+  endforeach
+  none_config_devices_h = configure_file(output: 'none-config-devices.h',
+                                         configuration: 
none_config_devices_data)
+  qemu_none_ss = ss.source_set()
+  qemu_none_ss.add(files('system/target-info-select.c'))
+  qemu_none_ss.add(target_info_def)
+  qemu_none_src = qemu_none_ss.apply(single_binary_config, strict: false)
+  qemu_none = static_library('qemu-none',
+                             sources: qemu_none_src.sources() + genh +
+                                      [none_config_target_h,
+                                       none_config_devices_h],
+                             dependencies: qemu_none_src.dependencies(),
+                             include_directories: include_directories(
+                               'target' / 'none'),
+                             c_args: [
+                               '-DCOMPILING_PER_TARGET',
+                               '-DCONFIG_TARGET="none-config-target.h"',
+                               '-DCONFIG_DEVICES="none-config-devices.h"',
+                             ],
+                             build_by_default: false)
+  single_binary_objects += qemu_none.extract_objects(qemu_none_src.sources())
+
   single_binary_link_args = emulator_link_args
   single_binary_link_args += enable_modules ? ['@block.syms', '@qemu.syms'] : 
[]
   qemu_system_name = 'qemu-system'
diff --git a/qom/object.c b/qom/object.c
index 76b0b0806b3..2ce6c369df5 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -16,6 +16,7 @@
 #include "qom/object.h"
 #include "qom/object_interfaces.h"
 #include "qemu/target-info-qapi.h"
+#include "qemu/target-info-select.h"
 #include "qemu/cutils.h"
 #include "qemu/memalign.h"
 #include "qapi/visitor.h"
@@ -171,7 +172,12 @@ static TypeImpl *type_register_internal(const TypeInfo 
*info)
         abort();
     }
 
-    if (info->is_available && !info->is_available(target_info())) {
+    /*
+     * Single-target binaries omit types that cannot run. The combined
+     * binary keeps them and filters with is_available per target.
+     */
+    if (!target_combined_binary() && info->is_available &&
+        !info->is_available(target_info())) {
         return NULL;
     }
 
diff --git a/stubs/meson.build b/stubs/meson.build
index 29b6644b254..3765537778d 100644
--- a/stubs/meson.build
+++ b/stubs/meson.build
@@ -3,6 +3,7 @@
 # below, so that it is clear who needs the stubbed functionality.
 
 stub_ss.add(files('cpu-get-clock.c'))
+stub_ss.add(files('target-info-select.c'))
 stub_ss.add(files('fdset.c'))
 stub_ss.add(files('iothread-lock.c'))
 stub_ss.add(files('is-daemonized.c'))
diff --git a/stubs/target-info-select.c b/stubs/target-info-select.c
new file mode 100644
index 00000000000..5c9e8dc6e19
--- /dev/null
+++ b/stubs/target-info-select.c
@@ -0,0 +1,14 @@
+#include "qemu/osdep.h"
+#include "qemu/target-info-select.h"
+#include "qapi/error.h"
+
+bool target_combined_binary(void)
+{
+    return false;
+}
+
+void target_info_select_by_name(const char *name, Error **errp)
+{
+    (void)name;
+    (void)errp;
+}
diff --git a/system/target-info-select.c b/system/target-info-select.c
new file mode 100644
index 00000000000..4b4a9fdf256
--- /dev/null
+++ b/system/target-info-select.c
@@ -0,0 +1,26 @@
+#include "qemu/osdep.h"
+#include "qemu/target-info-def.h"
+#include "qemu/target-info-select.h"
+#include "qapi/error.h"
+
+bool target_combined_binary(void)
+{
+    return true;
+}
+
+void target_info_select_by_name(const char *name, Error **errp)
+{
+    TargetInfoNode *node;
+
+    if (!name) {
+        name = "none";
+    }
+
+    QLIST_FOREACH(node, target_info_list(), next) {
+        if (!strcmp(name, node->info->target_name)) {
+            target_info_select(node->info);
+            return;
+        }
+    }
+    error_setg(errp, "target '%s' is not available", name);
+}
diff --git a/target/none/cpu-param.h b/target/none/cpu-param.h
new file mode 100644
index 00000000000..3c0818a2f02
--- /dev/null
+++ b/target/none/cpu-param.h
@@ -0,0 +1,7 @@
+#ifndef NONE_CPU_PARAM_H
+#define NONE_CPU_PARAM_H
+
+#define TARGET_PAGE_BITS 9
+#define TARGET_VIRT_ADDR_SPACE_BITS 64
+
+#endif
diff --git a/target/none/cpu-qom.h b/target/none/cpu-qom.h
new file mode 100644
index 00000000000..114faa8077a
--- /dev/null
+++ b/target/none/cpu-qom.h
@@ -0,0 +1,6 @@
+#ifndef QEMU_NONE_CPU_QOM_H
+#define QEMU_NONE_CPU_QOM_H
+
+#define TYPE_NONE_CPU NULL
+
+#endif
diff --git a/target/none/cpu.h b/target/none/cpu.h
new file mode 100644
index 00000000000..ffb9a0d28dc
--- /dev/null
+++ b/target/none/cpu.h
@@ -0,0 +1,18 @@
+#ifndef QEMU_NONE_CPU_H
+#define QEMU_NONE_CPU_H
+
+#include "cpu-qom.h"
+#include "hw/core/cpu.h"
+
+#define CPU_RESOLVING_TYPE TYPE_NONE_CPU
+
+typedef struct CPUArchState {
+    uint64_t unused;
+} CPUArchState;
+
+struct ArchCPU {
+    CPUState parent_obj;
+    CPUArchState env;
+};
+
+#endif
-- 
2.52.0.windows.1


Reply via email to