From patchwork Mon Jan 16 21:11:21 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eduardo Habkost X-Patchwork-Id: 9519573 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 8F3DB601C3 for ; Mon, 16 Jan 2017 21:35:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 80A1626E55 for ; Mon, 16 Jan 2017 21:35:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 758632811D; Mon, 16 Jan 2017 21:35:05 +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 DA84426E55 for ; Mon, 16 Jan 2017 21:35:04 +0000 (UTC) Received: from localhost ([::1]:59748 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cTEvf-0007BK-UE for patchwork-qemu-devel@patchwork.kernel.org; Mon, 16 Jan 2017 16:35:04 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50391) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cTEYw-0003Xs-DC for qemu-devel@nongnu.org; Mon, 16 Jan 2017 16:11:35 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cTEYv-000147-43 for qemu-devel@nongnu.org; Mon, 16 Jan 2017 16:11:34 -0500 Received: from mx1.redhat.com ([209.132.183.28]:60634) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cTEYu-00013y-Rg for qemu-devel@nongnu.org; Mon, 16 Jan 2017 16:11:33 -0500 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (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 1B34B3F1F6 for ; Mon, 16 Jan 2017 21:11:33 +0000 (UTC) Received: from localhost (ovpn-116-2.gru2.redhat.com [10.97.116.2]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v0GLBVLj007635; Mon, 16 Jan 2017 16:11:32 -0500 From: Eduardo Habkost To: qemu-devel@nongnu.org Date: Mon, 16 Jan 2017 19:11:21 -0200 Message-Id: <20170116211124.29245-2-ehabkost@redhat.com> In-Reply-To: <20170116211124.29245-1-ehabkost@redhat.com> References: <20170116211124.29245-1-ehabkost@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Mon, 16 Jan 2017 21:11:33 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v2 1/4] target-i386: Reorganize and document CPUID initialization steps 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: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP CPU runnability checks and CPU model expansion have slightly different requirements. Document the steps involved in loading a CPU model and realizing a CPU, so their requirements and purpose are clearly defined. This patch doesn't change any implementation. It just add comments, rename the x86_cpu_load_features() function for clarity (so it won't be confused with x86_cpu_load_def()), and move x86_cpu_filter_features() closer to it. Signed-off-by: Eduardo Habkost --- Changes v1 -> v2: * Small reword of comments --- target/i386/cpu.c | 102 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 71 insertions(+), 31 deletions(-) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index e0ca8c0288..65cb87f3e9 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -2060,7 +2060,7 @@ static void x86_cpu_parse_featurestr(const char *typename, char *features, } } -static void x86_cpu_load_features(X86CPU *cpu, Error **errp); +static void x86_cpu_expand_features(X86CPU *cpu, Error **errp); static int x86_cpu_filter_features(X86CPU *cpu); /* Check for missing features that may prevent the CPU class from @@ -2076,9 +2076,9 @@ static void x86_cpu_class_check_missing_features(X86CPUClass *xcc, xc = X86_CPU(object_new(object_class_get_name(OBJECT_CLASS(xcc)))); - x86_cpu_load_features(xc, &err); + x86_cpu_expand_features(xc, &err); if (err) { - /* Errors at x86_cpu_load_features should never happen, + /* Errors at x86_cpu_expand_features should never happen, * but in case it does, just report the model as not * runnable at all using the "type" property. */ @@ -2239,31 +2239,6 @@ static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w, return r; } -/* - * Filters CPU feature words based on host availability of each feature. - * - * Returns: 0 if all flags are supported by the host, non-zero otherwise. - */ -static int x86_cpu_filter_features(X86CPU *cpu) -{ - CPUX86State *env = &cpu->env; - FeatureWord w; - int rv = 0; - - for (w = 0; w < FEATURE_WORDS; w++) { - uint32_t host_feat = - x86_cpu_get_supported_feature_word(w, false); - uint32_t requested_features = env->features[w]; - env->features[w] &= host_feat; - cpu->filtered_features[w] = requested_features & ~env->features[w]; - if (cpu->filtered_features[w]) { - rv = 1; - } - } - - return rv; -} - static void x86_cpu_report_filtered_features(X86CPU *cpu) { FeatureWord w; @@ -3089,8 +3064,47 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu) env->features[FEAT_XSAVE_COMP_HI] = mask >> 32; } -/* Load CPUID data based on configured features */ -static void x86_cpu_load_features(X86CPU *cpu, Error **errp) +/***** Steps involved on loading and filtering CPUID data + * + * When initializing and realizing a CPU object, the steps + * involved in setting up CPUID data are: + * + * 1) Loading CPU model definition (X86CPUDefinition). This is + * implemented by x86_cpu_load_def() and should be completely + * transparent, as it is done automatically by instance_init. + * No code should need to look at X86CPUDefinition structs + * outside instance_init. + * + * 2) CPU expansion. This is done by realize before CPUID + * filtering, and will make sure host/accelerator data is + * loaded for CPU models that depend on host capabilities + * (e.g. "host"). Done by x86_cpu_expand_features(). + * + * 3) CPUID filtering. This initializes extra data related to + * CPUID, and checks if the host supports all capabilities + * required by the CPU. Runnability of a CPU model is + * determined at this step. Done by x86_cpu_filter_features(). + * + * Some operations don't require all steps to be performed. + * More precisely: + * + * - CPU instance creation (instance_init) will run only CPU + * model loading. CPU expansion can't run at instance_init-time + * because host/accelerator data may be not available yet. + * - CPU realization will perform both CPU model expansion and CPUID + * filtering, and return an error in case one of them fails. + * - query-cpu-definitions needs to run all 3 steps. It needs + * to run CPUID filtering, as the 'unavailable-features' + * field is set based on the filtering results. + * - The query-cpu-model-expansion QMP command only needs to run + * CPU model loading and CPU expansion. It should not filter + * any CPUID data based on host capabilities. + */ + +/* Expand CPU configuration data, based on configured features + * and host/accelerator capabilities when appropriate. + */ +static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) { CPUX86State *env = &cpu->env; FeatureWord w; @@ -3167,6 +3181,32 @@ out: } } +/* + * Finishes initialization of CPUID data, filters CPU feature + * words based on host availability of each feature. + * + * Returns: 0 if all flags are supported by the host, non-zero otherwise. + */ +static int x86_cpu_filter_features(X86CPU *cpu) +{ + CPUX86State *env = &cpu->env; + FeatureWord w; + int rv = 0; + + for (w = 0; w < FEATURE_WORDS; w++) { + uint32_t host_feat = + x86_cpu_get_supported_feature_word(w, false); + uint32_t requested_features = env->features[w]; + env->features[w] &= host_feat; + cpu->filtered_features[w] = requested_features & ~env->features[w]; + if (cpu->filtered_features[w]) { + rv = 1; + } + } + + return rv; +} + #define IS_INTEL_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_INTEL_1 && \ (env)->cpuid_vendor2 == CPUID_VENDOR_INTEL_2 && \ (env)->cpuid_vendor3 == CPUID_VENDOR_INTEL_3) @@ -3187,7 +3227,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) return; } - x86_cpu_load_features(cpu, &local_err); + x86_cpu_expand_features(cpu, &local_err); if (local_err) { goto out; }