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 <dinahbaum...@gmail.com> wrote: > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1480 > Signed-off-by: Dinah Baum <dinahbaum...@gmail.com> > > Signed-off-by: Dinah Baum <dinahbaum...@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 > >