This patch implements the QMP command "query-cpu-definitions" in the S390 context. The command returns a descending sorted list of cpu model names derived from the currently (in the current host context) supported set of cpu classes. That means a consumer can successfully request each reported cpu model. Implicitly, the first reported cpu model is the host cpu model.
request: {"execute": "query-cpu-definitions"} answer: {"return": [{"name": "2827-ga1"}, {"name": "2818-ga1"}, {"name": "2817-ga2"}, {"name": "2817-ga1"}, {"name": "2098-ga2"}, {"name": "2098-ga1"}, {"name": "2097-ga3"}, {"name": "2097-ga2"}, {"name": "2097-ga1"}, {"name": "2096-ga2"}, {"name": "2096-ga1"}, {"name": "2094-ga3"}, {"name": "2094-ga2"}, {"name": "2094-ga1"}, {"name": "2086-ga3"}, {"name": "2086-ga2"}, {"name": "2086-ga1"}, {"name": "2084-ga5"}, {"name": "2084-ga4"}, {"name": "2084-ga3"}, {"name": "2084-ga2"}, {"name": "2084-ga1"}, {"name": "2068-ga1"}, {"name": "2064-ga3"}, {"name": "2064-ga2"}, {"name": "2064-ga1"}]} Signed-off-by: Michael Mueller <m...@linux.vnet.ibm.com> --- target-s390x/cpu-models.c | 15 +++++++++++ target-s390x/cpu-models.h | 1 + target-s390x/cpu.c | 69 +++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 80 insertions(+), 5 deletions(-) diff --git a/target-s390x/cpu-models.c b/target-s390x/cpu-models.c index 68b978a..f07ff17 100644 --- a/target-s390x/cpu-models.c +++ b/target-s390x/cpu-models.c @@ -249,6 +249,21 @@ gint s390_cpu_class_asc_order_compare(gconstpointer a, gconstpointer b) return 0; } +/* compare order of two cpu classes for descending sort */ +gint s390_cpu_class_desc_order_compare(gconstpointer a, gconstpointer b) +{ + S390CPUClass *cc_a = S390_CPU_CLASS((ObjectClass *) a); + S390CPUClass *cc_b = S390_CPU_CLASS((ObjectClass *) b); + + if (cc_a->order < cc_b->order) { + return 1; + } + if (cc_a->order > cc_b->order) { + return -1; + } + return 0; +} + /* return machine class for specific machine type */ static void s390_machine_class_test_cpu_class(gpointer data, gpointer user_data) { diff --git a/target-s390x/cpu-models.h b/target-s390x/cpu-models.h index fd01876..9d02ce6 100644 --- a/target-s390x/cpu-models.h +++ b/target-s390x/cpu-models.h @@ -51,6 +51,7 @@ struct S390HostProps { int s390_fetch_kvm_host_props(struct S390HostProps *prop); int s390_request_kvm_cpu_config(S390CPUClass *cc); gint s390_cpu_class_asc_order_compare(gconstpointer a, gconstpointer b); +gint s390_cpu_class_desc_order_compare(gconstpointer a, gconstpointer b); int s390_setup_cpu_classes(struct S390HostProps *prop); ObjectClass *s390_cpu_class_by_name(const char *name); void s390_cpu_list_entry(gpointer data, gpointer user_data); diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c index 0fccc72..b790905 100644 --- a/target-s390x/cpu.c +++ b/target-s390x/cpu.c @@ -57,18 +57,77 @@ void s390_cpu_list(FILE *f, fprintf_function cpu_fprintf) } #ifndef CONFIG_USER_ONLY -CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp) -{ - CpuDefinitionInfoList *entry; +static void s390_query_cpu_definition(gpointer data, gpointer user_data) { + S390CPUClass *cc = S390_CPU_CLASS((ObjectClass *) data); + char model[16]; CpuDefinitionInfo *info; + CpuDefinitionInfoList *entry; + struct { + CpuDefinitionInfoList *head; + CpuDefinitionInfoList *tail; + } *cpu_definition = user_data; + + if (!cc->is_active) { + return; + } + info = g_malloc0(sizeof(*info)); - info->name = g_strdup("host"); + if (!info) { + return; + } + + snprintf(model, sizeof(model), "%04x-ga%u", cc->type, cc->ga); + info->name = g_strdup(model); + if (!info->name) { + return; + g_free(info); + } entry = g_malloc0(sizeof(*entry)); + if (!entry) { + g_free(info->name); + g_free(info); + return; + } entry->value = info; + entry->next = NULL; - return entry; + if (cpu_definition->tail) { + cpu_definition->tail->next = entry; + cpu_definition->tail = cpu_definition->tail->next; + } else { + cpu_definition->head = cpu_definition->tail = entry; + } +} + +CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp) +{ + if (kvm_enabled()) { + GSList *list; + + list = object_class_get_list(TYPE_S390_CPU, false); + list = g_slist_sort(list, s390_cpu_class_desc_order_compare); + struct { + CpuDefinitionInfoList *head; + CpuDefinitionInfoList *tail; + } cpu_definition = { + .head = NULL, + .tail = NULL, + }; + g_slist_foreach(list, s390_query_cpu_definition, &cpu_definition); + g_slist_free(list); + return cpu_definition.head; + } else { + CpuDefinitionInfoList *entry; + CpuDefinitionInfo *info; + + info = g_malloc0(sizeof(*info)); + info->name = g_strdup("host"); + entry = g_malloc0(sizeof(*entry)); + entry->value = info; + return entry; + } } #endif -- 1.8.3.1