diff mbox series

[RFC,v2,03/11] system/vl: Filter machine list available for a particular target binary

Message ID 20250418005059.4436-4-philmd@linaro.org
State New
Headers show
Series single-binary: Make hw/arm/ common | expand

Commit Message

Philippe Mathieu-Daudé April 18, 2025, 12:50 a.m. UTC
Binaries can register a QOM type to filter their machines
by filling their TargetInfo::machine_typename field.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 include/qemu/target_info-impl.h |  3 +++
 include/qemu/target_info.h      |  8 ++++++++
 system/vl.c                     | 14 ++++++++++++++
 target_info.c                   |  5 +++++
 4 files changed, 30 insertions(+)

Comments

Pierrick Bouvier April 18, 2025, 3:06 a.m. UTC | #1
On 4/17/25 17:50, Philippe Mathieu-Daudé wrote:
> Binaries can register a QOM type to filter their machines
> by filling their TargetInfo::machine_typename field.
> 
> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> ---
>   include/qemu/target_info-impl.h |  3 +++
>   include/qemu/target_info.h      |  8 ++++++++
>   system/vl.c                     | 14 ++++++++++++++
>   target_info.c                   |  5 +++++
>   4 files changed, 30 insertions(+)
> 
> diff --git a/include/qemu/target_info-impl.h b/include/qemu/target_info-impl.h
> index d5c94ed5296..990fb067d20 100644
> --- a/include/qemu/target_info-impl.h
> +++ b/include/qemu/target_info-impl.h
> @@ -16,6 +16,9 @@ typedef struct TargetInfo {
>       /* runtime equivalent of TARGET_NAME definition */
>       const char *const name;
>   
> +    /* QOM typename machines for this binary must implement */
> +    const char *const machine_typename;
> +
>   } TargetInfo;
>   
>   const TargetInfo *target_info(void);
> diff --git a/include/qemu/target_info.h b/include/qemu/target_info.h
> index 3f6cbbbd300..e9fd2fdd7b0 100644
> --- a/include/qemu/target_info.h
> +++ b/include/qemu/target_info.h
> @@ -16,4 +16,12 @@
>    */
>   const char *target_name(void);
>   
> +/**
> + * target_machine_interface_typename:
> + *
> + * Returns: Name of the QOM interface implemented by machines
> + *          usable on this target binary.
> + */
> +const char *target_machine_interface_typename(void);
> +
>   #endif
> diff --git a/system/vl.c b/system/vl.c
> index d8a0fe713c9..4e43e55afe7 100644
> --- a/system/vl.c
> +++ b/system/vl.c
> @@ -27,6 +27,7 @@
>   #include "qemu/datadir.h"
>   #include "qemu/units.h"
>   #include "qemu/module.h"
> +#include "qemu/target_info.h"
>   #include "exec/cpu-common.h"
>   #include "exec/page-vary.h"
>   #include "hw/qdev-properties.h"
> @@ -836,11 +837,17 @@ static bool usb_parse(const char *cmdline, Error **errp)
>   static MachineClass *find_machine(const char *name, GSList *machines)
>   {
>       GSList *el;
> +    const char *qom_typename_filter = target_machine_interface_typename();
>   
>       for (el = machines; el; el = el->next) {
>           MachineClass *mc = el->data;
>   
>           if (!strcmp(mc->name, name) || !g_strcmp0(mc->alias, name)) {
> +            if (qom_typename_filter
> +                && !object_class_dynamic_cast(el->data, qom_typename_filter)) {
> +                /* Machine is not for this binary: fail */
> +                return NULL;
> +            }
>               return mc;
>           }
>       }
> @@ -1563,6 +1570,7 @@ static void machine_help_func(const QDict *qdict)
>       g_autoptr(GSList) machines = NULL;
>       GSList *el;
>       const char *type = qdict_get_try_str(qdict, "type");
> +    const char *qom_typename_filter = target_machine_interface_typename();
>   
>       machines = object_class_get_list(TYPE_MACHINE, false);

We can replace change to system/vl.c with:

const char *machine_type = target_machine_interface_typename();
machines = object_class_get_list(machine_type, false);

>       if (type) {
> @@ -1577,6 +1585,12 @@ static void machine_help_func(const QDict *qdict)
>       machines = g_slist_sort(machines, machine_class_cmp);
>       for (el = machines; el; el = el->next) {
>           MachineClass *mc = el->data;
> +
> +        if (qom_typename_filter
> +            && !object_class_dynamic_cast(el->data, qom_typename_filter)) {
> +            /* Machine is not for this binary: skip */
> +            continue;
> +        }
>           if (mc->alias) {
>               printf("%-20s %s (alias of %s)\n", mc->alias, mc->desc, mc->name);
>           }
> diff --git a/target_info.c b/target_info.c
> index 877a6a15014..226eed1fd7d 100644
> --- a/target_info.c
> +++ b/target_info.c
> @@ -14,3 +14,8 @@ const char *target_name(void)
>   {
>       return target_info()->name;
>   }
> +
> +const char *target_machine_interface_typename(void)
> +{
> +    return target_info()->machine_typename;

And here:

const char *machine_type = target_info()->machine_typename;
if (!machine_type) {
	machine_type = TYPE_MACHINE;
}
return machine_type;

> +}

This way, there is no special case to handle anywhere, and we can safely 
replace occurrences of TYPE_MACHINE queries with 
target_machine_interface_typename().

As well, just a nit, but it's not important to know it's an interface, I 
would prefer a simpler name: target_machine_type();
Philippe Mathieu-Daudé April 18, 2025, 2:14 p.m. UTC | #2
On 18/4/25 05:06, Pierrick Bouvier wrote:
> On 4/17/25 17:50, Philippe Mathieu-Daudé wrote:
>> Binaries can register a QOM type to filter their machines
>> by filling their TargetInfo::machine_typename field.
>>
>> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
>> ---
>>   include/qemu/target_info-impl.h |  3 +++
>>   include/qemu/target_info.h      |  8 ++++++++
>>   system/vl.c                     | 14 ++++++++++++++
>>   target_info.c                   |  5 +++++
>>   4 files changed, 30 insertions(+)
>>
>> diff --git a/include/qemu/target_info-impl.h b/include/qemu/ 
>> target_info-impl.h
>> index d5c94ed5296..990fb067d20 100644
>> --- a/include/qemu/target_info-impl.h
>> +++ b/include/qemu/target_info-impl.h
>> @@ -16,6 +16,9 @@ typedef struct TargetInfo {
>>       /* runtime equivalent of TARGET_NAME definition */
>>       const char *const name;
>> +    /* QOM typename machines for this binary must implement */
>> +    const char *const machine_typename;
>> +
>>   } TargetInfo;
>>   const TargetInfo *target_info(void);
>> diff --git a/include/qemu/target_info.h b/include/qemu/target_info.h
>> index 3f6cbbbd300..e9fd2fdd7b0 100644
>> --- a/include/qemu/target_info.h
>> +++ b/include/qemu/target_info.h
>> @@ -16,4 +16,12 @@
>>    */
>>   const char *target_name(void);
>> +/**
>> + * target_machine_interface_typename:
>> + *
>> + * Returns: Name of the QOM interface implemented by machines
>> + *          usable on this target binary.
>> + */
>> +const char *target_machine_interface_typename(void);
>> +
>>   #endif
>> diff --git a/system/vl.c b/system/vl.c
>> index d8a0fe713c9..4e43e55afe7 100644
>> --- a/system/vl.c
>> +++ b/system/vl.c
>> @@ -27,6 +27,7 @@
>>   #include "qemu/datadir.h"
>>   #include "qemu/units.h"
>>   #include "qemu/module.h"
>> +#include "qemu/target_info.h"
>>   #include "exec/cpu-common.h"
>>   #include "exec/page-vary.h"
>>   #include "hw/qdev-properties.h"
>> @@ -836,11 +837,17 @@ static bool usb_parse(const char *cmdline, Error 
>> **errp)
>>   static MachineClass *find_machine(const char *name, GSList *machines)
>>   {
>>       GSList *el;
>> +    const char *qom_typename_filter = 
>> target_machine_interface_typename();
>>       for (el = machines; el; el = el->next) {
>>           MachineClass *mc = el->data;
>>           if (!strcmp(mc->name, name) || !g_strcmp0(mc->alias, name)) {
>> +            if (qom_typename_filter
>> +                && !object_class_dynamic_cast(el->data, 
>> qom_typename_filter)) {
>> +                /* Machine is not for this binary: fail */
>> +                return NULL;
>> +            }
>>               return mc;
>>           }
>>       }
>> @@ -1563,6 +1570,7 @@ static void machine_help_func(const QDict *qdict)
>>       g_autoptr(GSList) machines = NULL;
>>       GSList *el;
>>       const char *type = qdict_get_try_str(qdict, "type");
>> +    const char *qom_typename_filter = 
>> target_machine_interface_typename();
>>       machines = object_class_get_list(TYPE_MACHINE, false);
> 
> We can replace change to system/vl.c with:
> 
> const char *machine_type = target_machine_interface_typename();
> machines = object_class_get_list(machine_type, false);

Clever!

> 
>>       if (type) {
>> @@ -1577,6 +1585,12 @@ static void machine_help_func(const QDict *qdict)
>>       machines = g_slist_sort(machines, machine_class_cmp);
>>       for (el = machines; el; el = el->next) {
>>           MachineClass *mc = el->data;
>> +
>> +        if (qom_typename_filter
>> +            && !object_class_dynamic_cast(el->data, 
>> qom_typename_filter)) {
>> +            /* Machine is not for this binary: skip */
>> +            continue;
>> +        }
>>           if (mc->alias) {
>>               printf("%-20s %s (alias of %s)\n", mc->alias, mc->desc, 
>> mc->name);
>>           }
>> diff --git a/target_info.c b/target_info.c
>> index 877a6a15014..226eed1fd7d 100644
>> --- a/target_info.c
>> +++ b/target_info.c
>> @@ -14,3 +14,8 @@ const char *target_name(void)
>>   {
>>       return target_info()->name;
>>   }
>> +
>> +const char *target_machine_interface_typename(void)
>> +{
>> +    return target_info()->machine_typename;
> 
> And here:
> 
> const char *machine_type = target_info()->machine_typename;
> if (!machine_type) {
>      machine_type = TYPE_MACHINE;
> }
> return machine_type;
> 
>> +}
> 
> This way, there is no special case to handle anywhere, and we can safely 
> replace occurrences of TYPE_MACHINE queries with 
> target_machine_interface_typename().
> 
> As well, just a nit, but it's not important to know it's an interface, I 
> would prefer a simpler name: target_machine_type();
diff mbox series

Patch

diff --git a/include/qemu/target_info-impl.h b/include/qemu/target_info-impl.h
index d5c94ed5296..990fb067d20 100644
--- a/include/qemu/target_info-impl.h
+++ b/include/qemu/target_info-impl.h
@@ -16,6 +16,9 @@  typedef struct TargetInfo {
     /* runtime equivalent of TARGET_NAME definition */
     const char *const name;
 
+    /* QOM typename machines for this binary must implement */
+    const char *const machine_typename;
+
 } TargetInfo;
 
 const TargetInfo *target_info(void);
diff --git a/include/qemu/target_info.h b/include/qemu/target_info.h
index 3f6cbbbd300..e9fd2fdd7b0 100644
--- a/include/qemu/target_info.h
+++ b/include/qemu/target_info.h
@@ -16,4 +16,12 @@ 
  */
 const char *target_name(void);
 
+/**
+ * target_machine_interface_typename:
+ *
+ * Returns: Name of the QOM interface implemented by machines
+ *          usable on this target binary.
+ */
+const char *target_machine_interface_typename(void);
+
 #endif
diff --git a/system/vl.c b/system/vl.c
index d8a0fe713c9..4e43e55afe7 100644
--- a/system/vl.c
+++ b/system/vl.c
@@ -27,6 +27,7 @@ 
 #include "qemu/datadir.h"
 #include "qemu/units.h"
 #include "qemu/module.h"
+#include "qemu/target_info.h"
 #include "exec/cpu-common.h"
 #include "exec/page-vary.h"
 #include "hw/qdev-properties.h"
@@ -836,11 +837,17 @@  static bool usb_parse(const char *cmdline, Error **errp)
 static MachineClass *find_machine(const char *name, GSList *machines)
 {
     GSList *el;
+    const char *qom_typename_filter = target_machine_interface_typename();
 
     for (el = machines; el; el = el->next) {
         MachineClass *mc = el->data;
 
         if (!strcmp(mc->name, name) || !g_strcmp0(mc->alias, name)) {
+            if (qom_typename_filter
+                && !object_class_dynamic_cast(el->data, qom_typename_filter)) {
+                /* Machine is not for this binary: fail */
+                return NULL;
+            }
             return mc;
         }
     }
@@ -1563,6 +1570,7 @@  static void machine_help_func(const QDict *qdict)
     g_autoptr(GSList) machines = NULL;
     GSList *el;
     const char *type = qdict_get_try_str(qdict, "type");
+    const char *qom_typename_filter = target_machine_interface_typename();
 
     machines = object_class_get_list(TYPE_MACHINE, false);
     if (type) {
@@ -1577,6 +1585,12 @@  static void machine_help_func(const QDict *qdict)
     machines = g_slist_sort(machines, machine_class_cmp);
     for (el = machines; el; el = el->next) {
         MachineClass *mc = el->data;
+
+        if (qom_typename_filter
+            && !object_class_dynamic_cast(el->data, qom_typename_filter)) {
+            /* Machine is not for this binary: skip */
+            continue;
+        }
         if (mc->alias) {
             printf("%-20s %s (alias of %s)\n", mc->alias, mc->desc, mc->name);
         }
diff --git a/target_info.c b/target_info.c
index 877a6a15014..226eed1fd7d 100644
--- a/target_info.c
+++ b/target_info.c
@@ -14,3 +14,8 @@  const char *target_name(void)
 {
     return target_info()->name;
 }
+
+const char *target_machine_interface_typename(void)
+{
+    return target_info()->machine_typename;
+}