Move cpu_model +-feat parsing into a separate file so that it could be reused later for parsing similar format of sparc target
Signed-off-by: Igor Mammedov <imamm...@redhat.com> --- CC: Riku Voipio <riku.voi...@iki.fi> CC: Laurent Vivier <laur...@vivier.eu> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Richard Henderson <r...@twiddle.net> CC: Eduardo Habkost <ehabk...@redhat.com> --- include/qom/cpu.h | 6 ++ default-configs/i386-bsd-user.mak | 1 + default-configs/i386-linux-user.mak | 1 + default-configs/i386-softmmu.mak | 1 + default-configs/x86_64-bsd-user.mak | 1 + default-configs/x86_64-linux-user.mak | 1 + default-configs/x86_64-softmmu.mak | 1 + target/i386/cpu.c | 124 ++------------------------- util/Makefile.objs | 1 + util/legacy_cpu_features_parser.c | 153 ++++++++++++++++++++++++++++++++++ 10 files changed, 172 insertions(+), 118 deletions(-) create mode 100644 util/legacy_cpu_features_parser.c diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 7bfd50c..60aea03 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -1039,4 +1039,10 @@ extern const struct VMStateDescription vmstate_cpu_common; #define UNASSIGNED_CPU_INDEX -1 +int cpu_legacy_apply_features(Object *obj, GList *features, bool enable, + Error **errp); + +void cpu_legacy_parse_featurestr(const char *typename, char *features, + GList **plus_features, GList **minus_features, + Error **errp); #endif diff --git a/default-configs/i386-bsd-user.mak b/default-configs/i386-bsd-user.mak index af1b31a..b28a05f 100644 --- a/default-configs/i386-bsd-user.mak +++ b/default-configs/i386-bsd-user.mak @@ -1 +1,2 @@ # Default configuration for i386-bsd-user +CONFIG_LEGACY_CPU_FEATURES=y diff --git a/default-configs/i386-linux-user.mak b/default-configs/i386-linux-user.mak index 8657e68..c136967 100644 --- a/default-configs/i386-linux-user.mak +++ b/default-configs/i386-linux-user.mak @@ -1 +1,2 @@ # Default configuration for i386-linux-user +CONFIG_LEGACY_CPU_FEATURES=y diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak index d2ab2f6..e3e7c0e 100644 --- a/default-configs/i386-softmmu.mak +++ b/default-configs/i386-softmmu.mak @@ -59,3 +59,4 @@ CONFIG_SMBIOS=y CONFIG_HYPERV_TESTDEV=$(CONFIG_KVM) CONFIG_PXB=y CONFIG_ACPI_VMGENID=y +CONFIG_LEGACY_CPU_FEATURES=y diff --git a/default-configs/x86_64-bsd-user.mak b/default-configs/x86_64-bsd-user.mak index 73e5d34..952323c 100644 --- a/default-configs/x86_64-bsd-user.mak +++ b/default-configs/x86_64-bsd-user.mak @@ -1 +1,2 @@ # Default configuration for x86_64-bsd-user +CONFIG_LEGACY_CPU_FEATURES=y diff --git a/default-configs/x86_64-linux-user.mak b/default-configs/x86_64-linux-user.mak index bec1d9e..b513ef2 100644 --- a/default-configs/x86_64-linux-user.mak +++ b/default-configs/x86_64-linux-user.mak @@ -1 +1,2 @@ # Default configuration for x86_64-linux-user +CONFIG_LEGACY_CPU_FEATURES=y diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak index 9bde2f1..6594ddf 100644 --- a/default-configs/x86_64-softmmu.mak +++ b/default-configs/x86_64-softmmu.mak @@ -59,3 +59,4 @@ CONFIG_SMBIOS=y CONFIG_HYPERV_TESTDEV=$(CONFIG_KVM) CONFIG_PXB=y CONFIG_ACPI_VMGENID=y +CONFIG_LEGACY_CPU_FEATURES=y diff --git a/target/i386/cpu.c b/target/i386/cpu.c index c571772..91d3684 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -17,7 +17,6 @@ * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ #include "qemu/osdep.h" -#include "qemu/cutils.h" #include "cpu.h" #include "exec/exec-all.h" @@ -1970,13 +1969,6 @@ static PropertyInfo qdev_prop_spinlocks = { /* Convert all '_' in a feature string option name to '-', to make feature * name conform to QOM property naming rule, which uses '-' instead of '_'. */ -static inline void feat2prop(char *s) -{ - while ((s = strchr(s, '_'))) { - *s = '-'; - } -} - /* Return the feature property name for a feature flag bit */ static const char *x86_cpu_feature_name(FeatureWord w, int bitnr) { @@ -2005,100 +1997,11 @@ static const char *x86_cpu_feature_name(FeatureWord w, int bitnr) */ static GList *plus_features, *minus_features; -static gint compare_string(gconstpointer a, gconstpointer b) -{ - return g_strcmp0(a, b); -} - -/* Parse "+feature,-feature,feature=foo" CPU feature string - */ static void x86_cpu_parse_featurestr(const char *typename, char *features, Error **errp) { - char *featurestr; /* Single 'key=value" string being parsed */ - static bool cpu_globals_initialized; - bool ambiguous = false; - - if (cpu_globals_initialized) { - return; - } - cpu_globals_initialized = true; - - if (!features) { - return; - } - - for (featurestr = strtok(features, ","); - featurestr; - featurestr = strtok(NULL, ",")) { - const char *name; - const char *val = NULL; - char *eq = NULL; - char num[32]; - GlobalProperty *prop; - - /* Compatibility syntax: */ - if (featurestr[0] == '+') { - plus_features = g_list_append(plus_features, - g_strdup(featurestr + 1)); - continue; - } else if (featurestr[0] == '-') { - minus_features = g_list_append(minus_features, - g_strdup(featurestr + 1)); - continue; - } - - eq = strchr(featurestr, '='); - if (eq) { - *eq++ = 0; - val = eq; - } else { - val = "on"; - } - - feat2prop(featurestr); - name = featurestr; - - if (g_list_find_custom(plus_features, name, compare_string)) { - error_report("warning: Ambiguous CPU model string. " - "Don't mix both \"+%s\" and \"%s=%s\"", - name, name, val); - ambiguous = true; - } - if (g_list_find_custom(minus_features, name, compare_string)) { - error_report("warning: Ambiguous CPU model string. " - "Don't mix both \"-%s\" and \"%s=%s\"", - name, name, val); - ambiguous = true; - } - - /* Special case: */ - if (!strcmp(name, "tsc-freq")) { - int ret; - uint64_t tsc_freq; - - ret = qemu_strtosz_metric(val, NULL, &tsc_freq); - if (ret < 0 || tsc_freq > INT64_MAX) { - error_setg(errp, "bad numerical value %s", val); - return; - } - snprintf(num, sizeof(num), "%" PRId64, tsc_freq); - val = num; - name = "tsc-frequency"; - } - - prop = g_new0(typeof(*prop), 1); - prop->driver = typename; - prop->property = g_strdup(name); - prop->value = g_strdup(val); - prop->errp = &error_fatal; - qdev_prop_register_global(prop); - } - - if (ambiguous) { - error_report("warning: Compatibility of ambiguous CPU model " - "strings won't be kept on future QEMU versions"); - } + cpu_legacy_parse_featurestr(typename, features, + &plus_features, &minus_features, errp); } static void x86_cpu_expand_features(X86CPU *cpu, Error **errp); @@ -3370,8 +3273,6 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) { CPUX86State *env = &cpu->env; FeatureWord w; - GList *l; - Error *local_err = NULL; /*TODO: Now cpu->max_features doesn't overwrite features * set using QOM properties, and we can convert @@ -3389,20 +3290,12 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) } } - for (l = plus_features; l; l = l->next) { - const char *prop = l->data; - object_property_set_bool(OBJECT(cpu), true, prop, &local_err); - if (local_err) { - goto out; - } + if (cpu_legacy_apply_features(OBJECT(cpu), plus_features, true, errp)) { + return; } - for (l = minus_features; l; l = l->next) { - const char *prop = l->data; - object_property_set_bool(OBJECT(cpu), false, prop, &local_err); - if (local_err) { - goto out; - } + if (cpu_legacy_apply_features(OBJECT(cpu), minus_features, false, errp)) { + return; } if (!kvm_enabled() || !cpu->expose_kvm) { @@ -3440,11 +3333,6 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) if (env->cpuid_xlevel2 == UINT32_MAX) { env->cpuid_xlevel2 = env->cpuid_min_xlevel2; } - -out: - if (local_err != NULL) { - error_propagate(errp, local_err); - } } /* diff --git a/util/Makefile.objs b/util/Makefile.objs index 50a55ec..14e28f7 100644 --- a/util/Makefile.objs +++ b/util/Makefile.objs @@ -45,3 +45,4 @@ util-obj-y += qht.o util-obj-y += range.o util-obj-y += stats64.o util-obj-y += systemd.o +util-obj-$(CONFIG_LEGACY_CPU_FEATURES) += legacy_cpu_features_parser.o diff --git a/util/legacy_cpu_features_parser.c b/util/legacy_cpu_features_parser.c new file mode 100644 index 0000000..f2e3b81 --- /dev/null +++ b/util/legacy_cpu_features_parser.c @@ -0,0 +1,153 @@ +/* Support for legacy -cpu cpu,features CLI option with +-feat syntax, + * used by x86/sparc targets + * + * Author: Andreas Färber <afaer...@suse.de> + * Author: Andre Przywara <andre.przyw...@amd.com> + * Author: Eduardo Habkost <ehabk...@redhat.com> + * Author: Igor Mammedov <imamm...@redhat.com> + * Author: Paolo Bonzini <pbonz...@redhat.com> + * Author: Markus Armbruster <arm...@redhat.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu/cutils.h" +#include "qom/cpu.h" +#include "qemu/error-report.h" +#include "hw/qdev-properties.h" + +/* DO NOT USE WITH NEW CODE */ +int cpu_legacy_apply_features(Object *obj, GList *features, bool enable, + Error **errp) +{ + GList *l; + Error *local_err = NULL; + + for (l = features; l; l = l->next) { + const char *prop = l->data; + object_property_set_bool(obj, enable, prop, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return 1; + } + } + return 0; +} + +static inline void feat2prop(char *s) +{ + while ((s = strchr(s, '_'))) { + *s = '-'; + } +} + +static gint compare_string(gconstpointer a, gconstpointer b) +{ + return g_strcmp0(a, b); +} + +/* DO NOT USE WITH NEW CODE + * Parse "+feature,-feature,feature=foo" CPU feature string + */ +void cpu_legacy_parse_featurestr(const char *typename, char *features, + GList **plus_features, GList **minus_features, + Error **errp) +{ + char *featurestr; /* Single 'key=value" string being parsed */ + static bool cpu_globals_initialized; + bool ambiguous = false; + + if (cpu_globals_initialized) { + return; + } + cpu_globals_initialized = true; + + if (!features) { + return; + } + + for (featurestr = strtok(features, ","); + featurestr; + featurestr = strtok(NULL, ",")) { + const char *name; + const char *val = NULL; + char *eq = NULL; + char num[32]; + GlobalProperty *prop; + + /* Compatibility syntax: */ + if (featurestr[0] == '+') { + *plus_features = g_list_append(*plus_features, + g_strdup(featurestr + 1)); + continue; + } else if (featurestr[0] == '-') { + *minus_features = g_list_append(*minus_features, + g_strdup(featurestr + 1)); + continue; + } + + eq = strchr(featurestr, '='); + if (eq) { + *eq++ = 0; + val = eq; + } else { + val = "on"; + } + + feat2prop(featurestr); + name = featurestr; + + if (g_list_find_custom(*plus_features, name, compare_string)) { + error_report("warning: Ambiguous CPU model string. " + "Don't mix both \"+%s\" and \"%s=%s\"", + name, name, val); + ambiguous = true; + } + if (g_list_find_custom(*minus_features, name, compare_string)) { + error_report("warning: Ambiguous CPU model string. " + "Don't mix both \"-%s\" and \"%s=%s\"", + name, name, val); + ambiguous = true; + } + + /* Special case: */ + if (!strcmp(name, "tsc-freq")) { + int ret; + uint64_t tsc_freq; + + ret = qemu_strtosz_metric(val, NULL, &tsc_freq); + if (ret < 0 || tsc_freq > INT64_MAX) { + error_setg(errp, "bad numerical value %s", val); + return; + } + snprintf(num, sizeof(num), "%" PRId64, tsc_freq); + val = num; + name = "tsc-frequency"; + } + + prop = g_new0(typeof(*prop), 1); + prop->driver = typename; + prop->property = g_strdup(name); + prop->value = g_strdup(val); + prop->errp = &error_fatal; + qdev_prop_register_global(prop); + } + + if (ambiguous) { + error_report("warning: Compatibility of ambiguous CPU model " + "strings won't be kept on future QEMU versions"); + } +} -- 2.7.4