From patchwork Thu Jul 7 19:59:15 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eduardo Habkost X-Patchwork-Id: 9219579 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 08504607D9 for ; Thu, 7 Jul 2016 20:05:19 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EDF9728505 for ; Thu, 7 Jul 2016 20:05:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E2C6028508; Thu, 7 Jul 2016 20:05:18 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 427D328505 for ; Thu, 7 Jul 2016 20:05:18 +0000 (UTC) Received: from localhost ([::1]:42059 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bLFXx-0002R8-Bt for patchwork-qemu-devel@patchwork.kernel.org; Thu, 07 Jul 2016 16:05:17 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51207) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bLFSs-0004QV-EJ for qemu-devel@nongnu.org; Thu, 07 Jul 2016 16:00:08 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bLFSq-0004OA-7u for qemu-devel@nongnu.org; Thu, 07 Jul 2016 16:00:01 -0400 Received: from mx1.redhat.com ([209.132.183.28]:37466) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bLFSp-0004Nv-W6 for qemu-devel@nongnu.org; Thu, 07 Jul 2016 16:00:00 -0400 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7F22B7EBCD; Thu, 7 Jul 2016 19:59:59 +0000 (UTC) Received: from localhost (vpn1-4-171.gru2.redhat.com [10.97.4.171]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u67JxvEb007832; Thu, 7 Jul 2016 15:59:58 -0400 From: Eduardo Habkost To: Peter Maydell Date: Thu, 7 Jul 2016 16:59:15 -0300 Message-Id: <1467921562-11796-10-git-send-email-ehabkost@redhat.com> In-Reply-To: <1467921562-11796-1-git-send-email-ehabkost@redhat.com> References: <1467921562-11796-1-git-send-email-ehabkost@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Thu, 07 Jul 2016 19:59:59 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 09/16] cpu: Use CPUClass->parse_features() as convertor to global properties X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paolo Bonzini , Igor Mammedov , qemu-devel@nongnu.org, Richard Henderson Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Igor Mammedov Currently CPUClass->parse_features() is used to parse -cpu features string and set properties on created CPU instances. But considering that features specified by -cpu apply to every created CPU instance, it doesn't make sense to parse the same features string for every CPU created. It also makes every target that cares about parsing features string explicitly call CPUClass->parse_features() parser, which gets in a way if we consider using generic device_add for CPU hotplug as device_add has not a clue about CPU specific hooks. Turns out we can use global properties mechanism to set properties on every created CPU instance for a given type. That way it's possible to convert CPU features into a set of global properties for CPU type specified by -cpu cpu_model and common Device.device_post_init() will apply them to CPU of given type automatically regardless whether it's manually created CPU or CPU created with help of device_add. Signed-off-by: Igor Mammedov Reviewed-by: Eduardo Habkost Signed-off-by: Eduardo Habkost --- hw/arm/virt.c | 7 ++++--- include/qom/cpu.h | 2 +- qom/cpu.c | 41 +++++++++++++++++++++++++++++------------ target-i386/cpu.c | 26 ++++++++++++++++++++------ 4 files changed, 54 insertions(+), 22 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 6e098af..ae90ca5 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1261,6 +1261,7 @@ static void machvirt_init(MachineState *machine) for (n = 0; n < smp_cpus; n++) { ObjectClass *oc = cpu_class_by_name(TYPE_ARM_CPU, cpustr[0]); + const char *typename = object_class_get_name(oc); CPUClass *cc = CPU_CLASS(oc); Object *cpuobj; Error *err = NULL; @@ -1270,10 +1271,10 @@ static void machvirt_init(MachineState *machine) error_report("Unable to find CPU definition"); exit(1); } - cpuobj = object_new(object_class_get_name(oc)); + /* convert -smp CPU options specified by the user into global props */ + cc->parse_features(typename, cpuopts, &err); + cpuobj = object_new(typename); - /* Handle any CPU options specified by the user */ - cc->parse_features(CPU(cpuobj), cpuopts, &err); g_free(cpuopts); if (err) { error_report_err(err); diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 32f3af3..cacb100 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -134,7 +134,7 @@ typedef struct CPUClass { /*< public >*/ ObjectClass *(*class_by_name)(const char *cpu_model); - void (*parse_features)(CPUState *cpu, char *str, Error **errp); + void (*parse_features)(const char *typename, char *str, Error **errp); void (*reset)(CPUState *cpu); int reset_dump_flags; diff --git a/qom/cpu.c b/qom/cpu.c index 751e992..2a0d9fe 100644 --- a/qom/cpu.c +++ b/qom/cpu.c @@ -28,6 +28,7 @@ #include "exec/log.h" #include "qemu/error-report.h" #include "sysemu/sysemu.h" +#include "hw/qdev-properties.h" bool cpu_exists(int64_t id) { @@ -46,7 +47,7 @@ bool cpu_exists(int64_t id) CPUState *cpu_generic_init(const char *typename, const char *cpu_model) { char *str, *name, *featurestr; - CPUState *cpu; + CPUState *cpu = NULL; ObjectClass *oc; CPUClass *cc; Error *err = NULL; @@ -60,16 +61,18 @@ CPUState *cpu_generic_init(const char *typename, const char *cpu_model) return NULL; } - cpu = CPU(object_new(object_class_get_name(oc))); - cc = CPU_GET_CLASS(cpu); - + cc = CPU_CLASS(oc); featurestr = strtok(NULL, ","); - cc->parse_features(cpu, featurestr, &err); + /* TODO: all callers of cpu_generic_init() need to be converted to + * call parse_features() only once, before calling cpu_generic_init(). + */ + cc->parse_features(object_class_get_name(oc), featurestr, &err); g_free(str); if (err != NULL) { goto out; } + cpu = CPU(object_new(object_class_get_name(oc))); object_property_set_bool(OBJECT(cpu), true, "realized", &err); out: @@ -282,25 +285,39 @@ static ObjectClass *cpu_common_class_by_name(const char *cpu_model) return NULL; } -static void cpu_common_parse_features(CPUState *cpu, char *features, +static void cpu_common_parse_features(const char *typename, char *features, Error **errp) { char *featurestr; /* Single "key=value" string being parsed */ char *val; - Error *err = NULL; + static bool cpu_globals_initialized; + + /* TODO: all callers of ->parse_features() need to be changed to + * call it only once, so we can remove this check (or change it + * to assert(!cpu_globals_initialized). + * Current callers of ->parse_features() are: + * - machvirt_init() + * - cpu_generic_init() + * - cpu_x86_create() + */ + if (cpu_globals_initialized) { + return; + } + cpu_globals_initialized = true; featurestr = features ? strtok(features, ",") : NULL; while (featurestr) { val = strchr(featurestr, '='); if (val) { + GlobalProperty *prop = g_new0(typeof(*prop), 1); *val = 0; val++; - object_property_parse(OBJECT(cpu), val, featurestr, &err); - if (err) { - error_propagate(errp, err); - return; - } + prop->driver = typename; + prop->property = g_strdup(featurestr); + prop->value = g_strdup(val); + prop->errp = &error_fatal; + qdev_prop_register_global(prop); } else { error_setg(errp, "Expected key=value format, found %s.", featurestr); diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 0b286e1..16977d5 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1958,12 +1958,17 @@ static FeatureWordArray minus_features = { 0 }; /* Parse "+feature,-feature,feature=foo" CPU feature string */ -static void x86_cpu_parse_featurestr(CPUState *cs, char *features, +static void x86_cpu_parse_featurestr(const char *typename, char *features, Error **errp) { - X86CPU *cpu = X86_CPU(cs); char *featurestr; /* Single 'key=value" string being parsed */ Error *local_err = NULL; + static bool cpu_globals_initialized; + + if (cpu_globals_initialized) { + return; + } + cpu_globals_initialized = true; if (!features) { return; @@ -1976,6 +1981,7 @@ static void x86_cpu_parse_featurestr(CPUState *cs, char *features, const char *val = NULL; char *eq = NULL; char num[32]; + GlobalProperty *prop; /* Compatibility syntax: */ if (featurestr[0] == '+') { @@ -2013,7 +2019,12 @@ static void x86_cpu_parse_featurestr(CPUState *cs, char *features, name = "tsc-frequency"; } - object_property_parse(OBJECT(cpu), val, name, &local_err); + 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 (local_err) { @@ -2202,9 +2213,11 @@ X86CPU *cpu_x86_create(const char *cpu_model, Error **errp) { X86CPU *cpu = NULL; ObjectClass *oc; + CPUClass *cc; gchar **model_pieces; char *name, *features; Error *error = NULL; + const char *typename; model_pieces = g_strsplit(cpu_model, ",", 2); if (!model_pieces[0]) { @@ -2219,10 +2232,11 @@ X86CPU *cpu_x86_create(const char *cpu_model, Error **errp) error_setg(&error, "Unable to find CPU definition: %s", name); goto out; } + cc = CPU_CLASS(oc); + typename = object_class_get_name(oc); - cpu = X86_CPU(object_new(object_class_get_name(oc))); - - x86_cpu_parse_featurestr(CPU(cpu), features, &error); + cc->parse_features(typename, features, &error); + cpu = X86_CPU(object_new(typename)); if (error) { goto out; }