Change parsing of -cpu argument to allow -cpu cpu,help to print options for the CPU type similar to how the '-device' option works.
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1480 Signed-off-by: Dinah Baum <dinahbaum...@gmail.com> --- cpu.c | 41 +++++++++++++++++++++++++++++++++++++++ include/exec/cpu-common.h | 2 ++ include/qapi/qmp/qdict.h | 2 ++ qemu-options.hx | 7 ++++--- qobject/qdict.c | 5 +++++ softmmu/vl.c | 36 ++++++++++++++++++++++++++++++++-- 6 files changed, 88 insertions(+), 5 deletions(-) diff --git a/cpu.c b/cpu.c index daf4e1ff0d..5f8a72e51f 100644 --- a/cpu.c +++ b/cpu.c @@ -23,7 +23,9 @@ #include "exec/target_page.h" #include "hw/qdev-core.h" #include "hw/qdev-properties.h" +#include "qemu/cutils.h" #include "qemu/error-report.h" +#include "qemu/qemu-print.h" #include "migration/vmstate.h" #ifdef CONFIG_USER_ONLY #include "qemu.h" @@ -43,6 +45,8 @@ #include "trace/trace-root.h" #include "qemu/accel.h" #include "qemu/plugin.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(target_ulong addr) { diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index ec6024dfde..8fc05307ad 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -174,5 +174,7 @@ typedef void (*cpu_model_expansion_func)(CpuModelExpansionType type, CpuModelExpansionInfo *get_cpu_model_expansion_info(CpuModelExpansionType type, CpuModelInfo *model, Error **errp); +void list_cpu_model_expansion(CpuModelExpansionType type, + CpuModelInfo *model, Error **errp); #endif /* CPU_COMMON_H */ diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h index 82e90fc072..1ff9523a13 100644 --- a/include/qapi/qmp/qdict.h +++ b/include/qapi/qmp/qdict.h @@ -68,4 +68,6 @@ 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 59bdf67a2c..10601626b7 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 ea20b23e4c..af6753a7e3 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -500,6 +500,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; @@ -1147,6 +1156,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(cpu_option); + 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; @@ -2431,8 +2460,9 @@ static void qemu_process_help_options(void) * type and the user did not specify one, so that the user doesn't need * to say '-cpu help -machine something'. */ - if (cpu_option && is_help_option(cpu_option)) { - list_cpus(cpu_option); + Error *errp = NULL; + if (qemu_opts_foreach(qemu_find_opts("cpu"), + cpu_help_func, NULL, &errp)) { exit(0); } @@ -2673,6 +2703,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]); @@ -2724,6 +2755,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