From patchwork Fri Feb 5 13:42:05 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Cooper X-Patchwork-Id: 8234721 Return-Path: X-Original-To: patchwork-xen-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 00490BEEE5 for ; Fri, 5 Feb 2016 14:04:30 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id CC2A3203A9 for ; Fri, 5 Feb 2016 14:04:28 +0000 (UTC) Received: from lists.xen.org (lists.xenproject.org [50.57.142.19]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7C2A3203A5 for ; Fri, 5 Feb 2016 14:04:27 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xen.org) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1aRgxk-0000TN-Nq; Fri, 05 Feb 2016 14:02:16 +0000 Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1aRgxg-0000Jf-8x for xen-devel@lists.xen.org; Fri, 05 Feb 2016 14:02:12 +0000 Received: from [85.158.139.211] by server-2.bemta-5.messagelabs.com id 5A/6F-21594-36BA4B65; Fri, 05 Feb 2016 14:02:11 +0000 X-Env-Sender: prvs=8364524b4=Andrew.Cooper3@citrix.com X-Msg-Ref: server-6.tower-206.messagelabs.com!1454680924!20279727!4 X-Originating-IP: [66.165.176.63] X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n, received_headers: No Received headers X-StarScan-Received: X-StarScan-Version: 7.35.1; banners=-,-,- X-VirusChecked: Checked Received: (qmail 58447 invoked from network); 5 Feb 2016 14:02:10 -0000 Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63) by server-6.tower-206.messagelabs.com with RC4-SHA encrypted SMTP; 5 Feb 2016 14:02:10 -0000 X-IronPort-AV: E=Sophos;i="5.22,400,1449532800"; d="scan'208";a="336333924" From: Andrew Cooper To: Xen-devel Date: Fri, 5 Feb 2016 13:42:05 +0000 Message-ID: <1454679743-18133-13-git-send-email-andrew.cooper3@citrix.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1454679743-18133-1-git-send-email-andrew.cooper3@citrix.com> References: <1454679743-18133-1-git-send-email-andrew.cooper3@citrix.com> MIME-Version: 1.0 X-DLP: MIA1 Cc: Andrew Cooper , Jan Beulich Subject: [Xen-devel] [PATCH v2 12/30] xen/x86: Generate deep dependencies of features X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Some features depend on other features. Working out and maintaining the exact dependency tree is complicated, so it is expressed in the automatic generation script, and flattened for faster runtime use. Signed-off-by: Andrew Cooper --- CC: Jan Beulich For all intents an purposes, new in v2. --- xen/arch/x86/cpuid.c | 54 +++++++++++++++++++++++++++++++++ xen/include/asm-x86/cpuid.h | 2 ++ xen/tools/gen-cpuid.py | 73 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 128 insertions(+), 1 deletion(-) diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c index 1af0e6c..25dcd0e 100644 --- a/xen/arch/x86/cpuid.c +++ b/xen/arch/x86/cpuid.c @@ -12,6 +12,7 @@ const uint32_t inverted_features[] = INIT_INVERTED_FEATURES; static const uint32_t pv_featuremask[] = INIT_PV_FEATURES; static const uint32_t hvm_shadow_featuremask[] = INIT_HVM_SHADOW_FEATURES; static const uint32_t hvm_hap_featuremask[] = INIT_HVM_HAP_FEATURES; +static const uint32_t deep_features[] = INIT_DEEP_FEATURES; uint32_t __read_mostly raw_featureset[FSCAPINTS]; uint32_t __read_mostly host_featureset[FSCAPINTS]; @@ -20,12 +21,34 @@ uint32_t __read_mostly hvm_featureset[FSCAPINTS]; static void sanitise_featureset(uint32_t *fs) { + uint32_t disabled_features[FSCAPINTS]; unsigned int i; for ( i = 0; i < FSCAPINTS; ++i ) { /* Clamp to known mask. */ fs[i] &= known_features[i]; + + /* + * Identify which features with deep dependencies have been + * disabled. + */ + disabled_features[i] = ~fs[i] & deep_features[i]; + } + + for_each_set_bit(i, (void *)disabled_features, + sizeof(disabled_features) * 8) + { + const uint32_t *dfs = lookup_deep_deps(i); + unsigned int j; + + ASSERT(dfs); /* deep_features[] should guarentee this. */ + + for ( j = 0; j < FSCAPINTS; ++j ) + { + fs[j] &= ~dfs[j]; + disabled_features[j] &= ~dfs[j]; + } } switch ( boot_cpu_data.x86_vendor ) @@ -153,6 +176,36 @@ void calculate_featuresets(void) calculate_hvm_featureset(); } +const uint32_t *lookup_deep_deps(uint32_t feature) +{ + static const struct { + uint32_t feature; + uint32_t fs[FSCAPINTS]; + } deep_deps[] = INIT_DEEP_DEPS; + unsigned int start = 0, end = ARRAY_SIZE(deep_deps); + + BUILD_BUG_ON(ARRAY_SIZE(deep_deps) != NR_DEEP_DEPS); + + /* Fast early exit. */ + if ( !test_bit(feature, deep_features) ) + return NULL; + + /* deep_deps[] is sorted. Perform a binary search. */ + while ( start < end ) + { + unsigned int mid = start + ((end - start) / 2); + + if ( deep_deps[mid].feature > feature ) + end = mid; + else if ( deep_deps[mid].feature < feature ) + start = mid + 1; + else + return deep_deps[mid].fs; + } + + return NULL; +} + static void __maybe_unused build_assertions(void) { BUILD_BUG_ON(ARRAY_SIZE(known_features) != FSCAPINTS); @@ -160,6 +213,7 @@ static void __maybe_unused build_assertions(void) BUILD_BUG_ON(ARRAY_SIZE(pv_featuremask) != FSCAPINTS); BUILD_BUG_ON(ARRAY_SIZE(hvm_shadow_featuremask) != FSCAPINTS); BUILD_BUG_ON(ARRAY_SIZE(hvm_hap_featuremask) != FSCAPINTS); + BUILD_BUG_ON(ARRAY_SIZE(deep_features) != FSCAPINTS); } /* diff --git a/xen/include/asm-x86/cpuid.h b/xen/include/asm-x86/cpuid.h index 18ba95b..cd7fa90 100644 --- a/xen/include/asm-x86/cpuid.h +++ b/xen/include/asm-x86/cpuid.h @@ -28,6 +28,8 @@ extern uint32_t hvm_featureset[FSCAPINTS]; void calculate_featuresets(void); +const uint32_t *lookup_deep_deps(uint32_t feature); + #endif /* __ASSEMBLY__ */ #endif /* !__X86_CPUID_H__ */ diff --git a/xen/tools/gen-cpuid.py b/xen/tools/gen-cpuid.py index 5f0f892..c44f124 100755 --- a/xen/tools/gen-cpuid.py +++ b/xen/tools/gen-cpuid.py @@ -138,6 +138,61 @@ def crunch_numbers(state): state.hvm_shadow = featureset_to_uint32s(state.raw_hvm_shadow, nr_entries) state.hvm_hap = featureset_to_uint32s(state.raw_hvm_hap, nr_entries) + deps = { + XSAVE: + (XSAVEOPT, XSAVEC, XGETBV1, XSAVES, AVX, MPX), + + AVX: + (FMA, FMA4, F16C, AVX2, XOP), + + PAE: + (LM, ), + + LM: + (CX16, LAHF_LM, PAGE1GB), + + XMM: + (LM, ), + + XMM2: + (LM, ), + + XMM3: + (LM, ), + + APIC: + (X2APIC, ), + + PSE: + (PSE36, ), + } + + deep_features = tuple(sorted(deps.keys())) + state.deep_deps = {} + + for feat in deep_features: + + seen = [feat] + to_process = list(deps[feat]) + + while len(to_process): + f = to_process.pop(0) + + if f in seen: + raise Fail("ERROR: Cycle found with %s when processing %s" + % (state.names[f], state.names[feat])) + + seen.append(f) + to_process.extend(deps.get(f, [])) + + state.deep_deps[feat] = seen[1:] + + state.deep_features = featureset_to_uint32s(deps.keys(), nr_entries) + state.nr_deep_deps = len(state.deep_deps.keys()) + + for k, v in state.deep_deps.iteritems(): + state.deep_deps[k] = featureset_to_uint32s(v, nr_entries) + def write_results(state): state.output.write( @@ -164,6 +219,12 @@ def write_results(state): #define INIT_HVM_SHADOW_FEATURES { \\\n%s\n} #define INIT_HVM_HAP_FEATURES { \\\n%s\n} + +#define NR_DEEP_DEPS %s + +#define INIT_DEEP_FEATURES { \\\n%s\n} + +#define INIT_DEEP_DEPS { \\ """ % (state.nr_entries, state.common, format_uint32s(state.known, 4), @@ -171,10 +232,20 @@ def write_results(state): format_uint32s(state.pv, 4), format_uint32s(state.hvm_shadow, 4), format_uint32s(state.hvm_hap, 4), + state.nr_deep_deps, + format_uint32s(state.deep_features, 4), )) + for dep in sorted(state.deep_deps.keys()): + state.output.write( + " { %#xU, /* %s */ { \\\n%s\n }, }, \\\n" + % (dep, state.names[dep], + format_uint32s(state.deep_deps[dep], 8) + )) + state.output.write( -""" +"""} + #endif /* __XEN_X86__FEATURESET_DATA__ */ """)