diff mbox series

[v3,3/3] cpu, softmmu/vl.c: Change parsing of -cpu argument to allow -cpu cpu, help to print options for the CPU type similar to how the '-device' option works.

Message ID 20230730064057.357598-4-dinahbaum123@gmail.com
State New
Headers show
Series Enable -cpu <cpu>,help | expand

Commit Message

Dinah B July 30, 2023, 6:40 a.m. UTC
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1480
Signed-off-by: Dinah Baum <dinahbaum123@gmail.com>

Signed-off-by: Dinah Baum <dinahbaum123@gmail.com>
---
 cpu.c                    | 41 ++++++++++++++++++++++++++++++++++++++++
 include/qapi/qmp/qdict.h |  1 +
 qemu-options.hx          |  7 ++++---
 qobject/qdict.c          |  5 +++++
 softmmu/vl.c             | 35 +++++++++++++++++++++++++++++++++-
 5 files changed, 85 insertions(+), 4 deletions(-)

Comments

Dinah B Aug. 1, 2023, 1:02 p.m. UTC | #1
Just realized that the commit message on this one got a little mangled. I'm
happy to revise it but I'd prefer to get the code reviewed first before
doing a purely commit message change.

-Dinah

On Sun, Jul 30, 2023 at 2:41 AM Dinah Baum <dinahbaum123@gmail.com> wrote:

> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1480
> Signed-off-by: Dinah Baum <dinahbaum123@gmail.com>
>
> Signed-off-by: Dinah Baum <dinahbaum123@gmail.com>
> ---
>  cpu.c                    | 41 ++++++++++++++++++++++++++++++++++++++++
>  include/qapi/qmp/qdict.h |  1 +
>  qemu-options.hx          |  7 ++++---
>  qobject/qdict.c          |  5 +++++
>  softmmu/vl.c             | 35 +++++++++++++++++++++++++++++++++-
>  5 files changed, 85 insertions(+), 4 deletions(-)
>
> diff --git a/cpu.c b/cpu.c
> index a99d09cd47..9971ffeeba 100644
> --- a/cpu.c
> +++ b/cpu.c
> @@ -43,6 +43,10 @@
>  #include "trace/trace-root.h"
>  #include "qemu/accel.h"
>  #include "qemu/plugin.h"
> +#include "qemu/cutils.h"
> +#include "qemu/qemu-print.h"
> +#include "qapi/qmp/qdict.h"
> +#include "qapi/qmp/qobject.h"
>
>  uintptr_t qemu_host_page_size;
>  intptr_t qemu_host_page_mask;
> @@ -312,6 +316,43 @@ CpuModelExpansionInfo
> *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
>      return get_cpu_model_expansion_info(type, model, errp);
>  }
>
> +void list_cpu_model_expansion(CpuModelExpansionType type,
> +                              CpuModelInfo *model,
> +                              Error **errp)
> +{
> +    CpuModelExpansionInfo *expansion_info;
> +    QDict *qdict;
> +    QDictEntry *qdict_entry;
> +    const char *key;
> +    QObject *obj;
> +    QType q_type;
> +    GPtrArray *array;
> +    int i;
> +    const char *type_name;
> +
> +    expansion_info = get_cpu_model_expansion_info(type, model, errp);
> +    if (expansion_info) {
> +        qdict = qobject_to(QDict, expansion_info->model->props);
> +        if (qdict) {
> +            qemu_printf("%s features:\n", model->name);
> +            array = g_ptr_array_new();
> +            for (qdict_entry = (QDictEntry *)qdict_first(qdict);
> qdict_entry;
> +                 qdict_entry = (QDictEntry *)qdict_next(qdict,
> qdict_entry)) {
> +                g_ptr_array_add(array, qdict_entry);
> +            }
> +            g_ptr_array_sort(array, (GCompareFunc)dict_key_compare);
> +            for (i = 0; i < array->len; i++) {
> +                qdict_entry = array->pdata[i];
> +                key = qdict_entry_key(qdict_entry);
> +                obj = qdict_get(qdict, key);
> +                q_type = qobject_type(obj);
> +                type_name = QType_str(q_type);
> +                qemu_printf("  %s=<%s>\n", key, type_name);
> +            }
> +        }
> +    }
> +}
> +
>  #if defined(CONFIG_USER_ONLY)
>  void tb_invalidate_phys_addr(hwaddr addr)
>  {
> diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h
> index 82e90fc072..d0b6c3d358 100644
> --- a/include/qapi/qmp/qdict.h
> +++ b/include/qapi/qmp/qdict.h
> @@ -67,5 +67,6 @@ bool qdict_get_try_bool(const QDict *qdict, const char
> *key, bool def_value);
>  const char *qdict_get_try_str(const QDict *qdict, const char *key);
>
>  QDict *qdict_clone_shallow(const QDict *src);
> +int dict_key_compare(QDictEntry **entry1, QDictEntry **entry2);
>
>  #endif /* QDICT_H */
> diff --git a/qemu-options.hx b/qemu-options.hx
> index 29b98c3d4c..e0f0284927 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -169,11 +169,12 @@ SRST
>  ERST
>
>  DEF("cpu", HAS_ARG, QEMU_OPTION_cpu,
> -    "-cpu cpu        select CPU ('-cpu help' for list)\n", QEMU_ARCH_ALL)
> +    "-cpu cpu        select CPU ('-cpu help' for list)\n"
> +    "                use '-cpu cpu,help' to print possible properties\n",
> QEMU_ARCH_ALL)
>  SRST
>  ``-cpu model``
> -    Select CPU model (``-cpu help`` for list and additional feature
> -    selection)
> +    Select CPU model (``-cpu help`` and ``-cpu cpu,help``) for list and
> additional feature
> +    selection
>  ERST
>
>  DEF("accel", HAS_ARG, QEMU_OPTION_accel,
> diff --git a/qobject/qdict.c b/qobject/qdict.c
> index 8faff230d3..31407e62f6 100644
> --- a/qobject/qdict.c
> +++ b/qobject/qdict.c
> @@ -447,3 +447,8 @@ void qdict_unref(QDict *q)
>  {
>      qobject_unref(q);
>  }
> +
> +int dict_key_compare(QDictEntry **entry1, QDictEntry **entry2)
> +{
> +    return g_strcmp0(qdict_entry_key(*entry1), qdict_entry_key(*entry2));
> +}
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index b0b96f67fa..1fd87f2c06 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -501,6 +501,15 @@ static QemuOptsList qemu_action_opts = {
>      },
>  };
>
> +static QemuOptsList qemu_cpu_opts = {
> +    .name = "cpu",
> +    .implied_opt_name = "cpu",
> +    .head = QTAILQ_HEAD_INITIALIZER(qemu_cpu_opts.head),
> +    .desc = {
> +        { /* end of list */ }
> +    },
> +};
> +
>  const char *qemu_get_vm_name(void)
>  {
>      return qemu_name;
> @@ -1159,6 +1168,26 @@ static int device_init_func(void *opaque, QemuOpts
> *opts, Error **errp)
>      return 0;
>  }
>
> +static int cpu_help_func(void *opaque, QemuOpts *opts, Error **errp)
> +{
> +    CpuModelInfo *model;
> +
> +    if (cpu_option && is_help_option(cpu_option)) {
> +        list_cpus();
> +        return 1;
> +    }
> +
> +    if (!cpu_option || !qemu_opt_has_help_opt(opts)) {
> +        return 0;
> +    }
> +
> +    model = g_new0(CpuModelInfo, 1);
> +    model->name = (char *)qemu_opt_get(opts, "cpu");
> +    /* TODO: handle other expansion cases */
> +    list_cpu_model_expansion(CPU_MODEL_EXPANSION_TYPE_FULL, model, errp);
> +    return 1;
> +}
> +
>  static int chardev_init_func(void *opaque, QemuOpts *opts, Error **errp)
>  {
>      Error *local_err = NULL;
> @@ -2466,7 +2495,9 @@ static void qemu_process_help_options(void)
>          list_cpus();
>          exit(0);
>      }
> -
> +    if (qemu_opts_foreach(qemu_find_opts("cpu"), cpu_help_func, NULL,
> NULL)) {
> +        exit(0);
> +    }
>      if (qemu_opts_foreach(qemu_find_opts("device"),
>                            device_help_func, NULL, NULL)) {
>          exit(0);
> @@ -2704,6 +2735,7 @@ void qemu_init(int argc, char **argv)
>      qemu_add_opts(&qemu_semihosting_config_opts);
>      qemu_add_opts(&qemu_fw_cfg_opts);
>      qemu_add_opts(&qemu_action_opts);
> +    qemu_add_opts(&qemu_cpu_opts);
>      module_call_init(MODULE_INIT_OPTS);
>
>      error_init(argv[0]);
> @@ -2755,6 +2787,7 @@ void qemu_init(int argc, char **argv)
>              switch(popt->index) {
>              case QEMU_OPTION_cpu:
>                  /* hw initialization will check this */
> +                qemu_opts_parse_noisily(qemu_find_opts("cpu"), optarg,
> true);
>                  cpu_option = optarg;
>                  break;
>              case QEMU_OPTION_hda:
> --
> 2.30.2
>
>
Markus Armbruster Aug. 1, 2023, 2:09 p.m. UTC | #2
Dinah Baum <dinahbaum123@gmail.com> writes:

> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1480
> Signed-off-by: Dinah Baum <dinahbaum123@gmail.com>
>
> Signed-off-by: Dinah Baum <dinahbaum123@gmail.com>

Looks basically the same as v2, which means my review still applies.

Message-ID: <878rdbfww1.fsf@pond.sub.org>
https://lists.nongnu.org/archive/html/qemu-devel/2023-05/msg06699.html

If you need further assistance, just ask.
Dinah B Aug. 1, 2023, 9 p.m. UTC | #3
Thanks, I will fix this. I somehow didn't catch that you had replied to the
old one.

-Dinah

On Tue, Aug 1, 2023 at 10:10 AM Markus Armbruster <armbru@redhat.com> wrote:

> Dinah Baum <dinahbaum123@gmail.com> writes:
>
> > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1480
> > Signed-off-by: Dinah Baum <dinahbaum123@gmail.com>
> >
> > Signed-off-by: Dinah Baum <dinahbaum123@gmail.com>
>
> Looks basically the same as v2, which means my review still applies.
>
> Message-ID: <878rdbfww1.fsf@pond.sub.org>
> https://lists.nongnu.org/archive/html/qemu-devel/2023-05/msg06699.html
>
> If you need further assistance, just ask.
>
>
Markus Armbruster Aug. 2, 2023, 5:36 a.m. UTC | #4
Dinah B <dinahbaum123@gmail.com> writes:

> Thanks, I will fix this. I somehow didn't catch that you had replied to the
> old one.

Happens :)
Dinah B Nov. 14, 2023, 4:22 p.m. UTC | #5
Hi,

Is there a way to distinguish between qemu-system-* vs qemu-* builds?
At first I thought #CONFIG_LINUX_USER might be it but not all non-mmu
builds set this.

Thanks,
-Dinah

On Wed, Aug 2, 2023 at 1:36 AM Markus Armbruster <armbru@redhat.com> wrote:

> Dinah B <dinahbaum123@gmail.com> writes:
>
> > Thanks, I will fix this. I somehow didn't catch that you had replied to
> the
> > old one.
>
> Happens :)
>
>
Markus Armbruster Nov. 14, 2023, 5:44 p.m. UTC | #6
Dinah B <dinahbaum123@gmail.com> writes:

> Hi,
>
> Is there a way to distinguish between qemu-system-* vs qemu-* builds?
> At first I thought #CONFIG_LINUX_USER might be it but not all non-mmu
> builds set this.

What are you trying to accomplish?
Dinah B Dec. 11, 2023, 6:02 a.m. UTC | #7
Hi,

Due to extracting CPU features via a qmp command, it only works on
qemu-system-* builds.
Building qmp for non system builds strikes me as extreme overkill so I need
a way to exclude this from non system builds.
Or maybe there's a way to disentangle querying CPU features independent
from the qom or qmp based data structures it's currently intertwined with.

Thanks,
-Dinah

On Tue, Nov 14, 2023 at 12:44 PM Markus Armbruster <armbru@redhat.com>
wrote:

> Dinah B <dinahbaum123@gmail.com> writes:
>
> > Hi,
> >
> > Is there a way to distinguish between qemu-system-* vs qemu-* builds?
> > At first I thought #CONFIG_LINUX_USER might be it but not all non-mmu
> > builds set this.
>
> What are you trying to accomplish?
>
>
diff mbox series

Patch

diff --git a/cpu.c b/cpu.c
index a99d09cd47..9971ffeeba 100644
--- a/cpu.c
+++ b/cpu.c
@@ -43,6 +43,10 @@ 
 #include "trace/trace-root.h"
 #include "qemu/accel.h"
 #include "qemu/plugin.h"
+#include "qemu/cutils.h"
+#include "qemu/qemu-print.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qobject.h"
 
 uintptr_t qemu_host_page_size;
 intptr_t qemu_host_page_mask;
@@ -312,6 +316,43 @@  CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
     return get_cpu_model_expansion_info(type, model, errp);
 }
 
+void list_cpu_model_expansion(CpuModelExpansionType type,
+                              CpuModelInfo *model,
+                              Error **errp)
+{
+    CpuModelExpansionInfo *expansion_info;
+    QDict *qdict;
+    QDictEntry *qdict_entry;
+    const char *key;
+    QObject *obj;
+    QType q_type;
+    GPtrArray *array;
+    int i;
+    const char *type_name;
+
+    expansion_info = get_cpu_model_expansion_info(type, model, errp);
+    if (expansion_info) {
+        qdict = qobject_to(QDict, expansion_info->model->props);
+        if (qdict) {
+            qemu_printf("%s features:\n", model->name);
+            array = g_ptr_array_new();
+            for (qdict_entry = (QDictEntry *)qdict_first(qdict); qdict_entry;
+                 qdict_entry = (QDictEntry *)qdict_next(qdict, qdict_entry)) {
+                g_ptr_array_add(array, qdict_entry);
+            }
+            g_ptr_array_sort(array, (GCompareFunc)dict_key_compare);
+            for (i = 0; i < array->len; i++) {
+                qdict_entry = array->pdata[i];
+                key = qdict_entry_key(qdict_entry);
+                obj = qdict_get(qdict, key);
+                q_type = qobject_type(obj);
+                type_name = QType_str(q_type);
+                qemu_printf("  %s=<%s>\n", key, type_name);
+            }
+        }
+    }
+}
+
 #if defined(CONFIG_USER_ONLY)
 void tb_invalidate_phys_addr(hwaddr addr)
 {
diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h
index 82e90fc072..d0b6c3d358 100644
--- a/include/qapi/qmp/qdict.h
+++ b/include/qapi/qmp/qdict.h
@@ -67,5 +67,6 @@  bool qdict_get_try_bool(const QDict *qdict, const char *key, bool def_value);
 const char *qdict_get_try_str(const QDict *qdict, const char *key);
 
 QDict *qdict_clone_shallow(const QDict *src);
+int dict_key_compare(QDictEntry **entry1, QDictEntry **entry2);
 
 #endif /* QDICT_H */
diff --git a/qemu-options.hx b/qemu-options.hx
index 29b98c3d4c..e0f0284927 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -169,11 +169,12 @@  SRST
 ERST
 
 DEF("cpu", HAS_ARG, QEMU_OPTION_cpu,
-    "-cpu cpu        select CPU ('-cpu help' for list)\n", QEMU_ARCH_ALL)
+    "-cpu cpu        select CPU ('-cpu help' for list)\n"
+    "                use '-cpu cpu,help' to print possible properties\n", QEMU_ARCH_ALL)
 SRST
 ``-cpu model``
-    Select CPU model (``-cpu help`` for list and additional feature
-    selection)
+    Select CPU model (``-cpu help`` and ``-cpu cpu,help``) for list and additional feature
+    selection
 ERST
 
 DEF("accel", HAS_ARG, QEMU_OPTION_accel,
diff --git a/qobject/qdict.c b/qobject/qdict.c
index 8faff230d3..31407e62f6 100644
--- a/qobject/qdict.c
+++ b/qobject/qdict.c
@@ -447,3 +447,8 @@  void qdict_unref(QDict *q)
 {
     qobject_unref(q);
 }
+
+int dict_key_compare(QDictEntry **entry1, QDictEntry **entry2)
+{
+    return g_strcmp0(qdict_entry_key(*entry1), qdict_entry_key(*entry2));
+}
diff --git a/softmmu/vl.c b/softmmu/vl.c
index b0b96f67fa..1fd87f2c06 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -501,6 +501,15 @@  static QemuOptsList qemu_action_opts = {
     },
 };
 
+static QemuOptsList qemu_cpu_opts = {
+    .name = "cpu",
+    .implied_opt_name = "cpu",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_cpu_opts.head),
+    .desc = {
+        { /* end of list */ }
+    },
+};
+
 const char *qemu_get_vm_name(void)
 {
     return qemu_name;
@@ -1159,6 +1168,26 @@  static int device_init_func(void *opaque, QemuOpts *opts, Error **errp)
     return 0;
 }
 
+static int cpu_help_func(void *opaque, QemuOpts *opts, Error **errp)
+{
+    CpuModelInfo *model;
+
+    if (cpu_option && is_help_option(cpu_option)) {
+        list_cpus();
+        return 1;
+    }
+
+    if (!cpu_option || !qemu_opt_has_help_opt(opts)) {
+        return 0;
+    }
+
+    model = g_new0(CpuModelInfo, 1);
+    model->name = (char *)qemu_opt_get(opts, "cpu");
+    /* TODO: handle other expansion cases */
+    list_cpu_model_expansion(CPU_MODEL_EXPANSION_TYPE_FULL, model, errp);
+    return 1;
+}
+
 static int chardev_init_func(void *opaque, QemuOpts *opts, Error **errp)
 {
     Error *local_err = NULL;
@@ -2466,7 +2495,9 @@  static void qemu_process_help_options(void)
         list_cpus();
         exit(0);
     }
-
+    if (qemu_opts_foreach(qemu_find_opts("cpu"), cpu_help_func, NULL, NULL)) {
+        exit(0);
+    }
     if (qemu_opts_foreach(qemu_find_opts("device"),
                           device_help_func, NULL, NULL)) {
         exit(0);
@@ -2704,6 +2735,7 @@  void qemu_init(int argc, char **argv)
     qemu_add_opts(&qemu_semihosting_config_opts);
     qemu_add_opts(&qemu_fw_cfg_opts);
     qemu_add_opts(&qemu_action_opts);
+    qemu_add_opts(&qemu_cpu_opts);
     module_call_init(MODULE_INIT_OPTS);
 
     error_init(argv[0]);
@@ -2755,6 +2787,7 @@  void qemu_init(int argc, char **argv)
             switch(popt->index) {
             case QEMU_OPTION_cpu:
                 /* hw initialization will check this */
+                qemu_opts_parse_noisily(qemu_find_opts("cpu"), optarg, true);
                 cpu_option = optarg;
                 break;
             case QEMU_OPTION_hda: