@@ -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"
@@ -42,6 +44,8 @@
#include "hw/core/accel-cpu.h"
#include "trace/trace-root.h"
#include "qemu/accel.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qobject.h"
uintptr_t qemu_host_page_size;
intptr_t qemu_host_page_mask;
@@ -311,6 +315,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)
{
@@ -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 */
@@ -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 */
@@ -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,
@@ -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));
+}
@@ -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);
}
@@ -2672,6 +2702,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]);
@@ -2723,6 +2754,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:
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 <dinahbaum123@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(-)