From patchwork Fri Feb 5 13:41:59 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Cooper X-Patchwork-Id: 8234421 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 C3FA6BEEED for ; Fri, 5 Feb 2016 13:44:54 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id BEF6020383 for ; Fri, 5 Feb 2016 13:44:53 +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 8F83D20389 for ; Fri, 5 Feb 2016 13:44:52 +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 1aRgef-0006jR-62; Fri, 05 Feb 2016 13:42:33 +0000 Received: from mail6.bemta4.messagelabs.com ([85.158.143.247]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1aRgec-0006hX-Vw for xen-devel@lists.xen.org; Fri, 05 Feb 2016 13:42:31 +0000 Received: from [85.158.143.35] by server-3.bemta-4.messagelabs.com id 9A/AB-31122-6C6A4B65; Fri, 05 Feb 2016 13:42:30 +0000 X-Env-Sender: prvs=8364524b4=Andrew.Cooper3@citrix.com X-Msg-Ref: server-11.tower-21.messagelabs.com!1454679747!14189266!3 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 26861 invoked from network); 5 Feb 2016 13:42:29 -0000 Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63) by server-11.tower-21.messagelabs.com with RC4-SHA encrypted SMTP; 5 Feb 2016 13:42:29 -0000 X-IronPort-AV: E=Sophos;i="5.22,400,1449532800"; d="scan'208";a="336330111" From: Andrew Cooper To: Xen-devel Date: Fri, 5 Feb 2016 13:41:59 +0000 Message-ID: <1454679743-18133-7-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: MIA2 Cc: Andrew Cooper , Tim Deegan , Ian Campbell , Jan Beulich Subject: [Xen-devel] [PATCH v2 06/30] xen/x86: Script to automatically process featureset information 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 This script consumes include/public/arch-x86/cpufeatureset.h and generates a single include/asm-x86/cpuid-autogen.h containing all the processed information. Signed-off-by: Andrew Cooper Acked-by: Jan Beulich --- CC: Jan Beulich CC: Tim Deegan CC: Ian Campbell For all intents and purposes, new in v2. All generated information is now expressed by #defines (using C structure initialisers for most) and contained in a single header file. --- .gitignore | 1 + xen/include/Makefile | 10 ++ xen/include/asm-x86/cpufeature.h | 4 +- xen/tools/gen-cpuid.py | 191 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 205 insertions(+), 1 deletion(-) create mode 100755 xen/tools/gen-cpuid.py diff --git a/.gitignore b/.gitignore index 91f690c..b40453e 100644 --- a/.gitignore +++ b/.gitignore @@ -252,6 +252,7 @@ xen/include/headers.chk xen/include/headers++.chk xen/include/asm xen/include/asm-*/asm-offsets.h +xen/include/asm-x86/cpuid-autogen.h xen/include/compat/* xen/include/config/ xen/include/generated/ diff --git a/xen/include/Makefile b/xen/include/Makefile index 9c8188b..268bc9d 100644 --- a/xen/include/Makefile +++ b/xen/include/Makefile @@ -117,5 +117,15 @@ headers++.chk: $(PUBLIC_HEADERS) Makefile endif +ifeq ($(XEN_TARGET_ARCH),x86_64) + +$(BASEDIR)/include/asm-x86/cpuid-autogen.h: $(BASEDIR)/include/public/arch-x86/cpufeatureset.h $(BASEDIR)/tools/gen-cpuid.py FORCE + $(PYTHON) $(BASEDIR)/tools/gen-cpuid.py -i $^ -o $@.new + $(call move-if-changed,$@.new,$@) + +all: $(BASEDIR)/include/asm-x86/cpuid-autogen.h +endif + clean:: rm -rf compat headers.chk headers++.chk + rm -f $(BASEDIR)/include/asm-x86/cpuid-autogen.h diff --git a/xen/include/asm-x86/cpufeature.h b/xen/include/asm-x86/cpufeature.h index eb6eb63..d069563 100644 --- a/xen/include/asm-x86/cpufeature.h +++ b/xen/include/asm-x86/cpufeature.h @@ -13,7 +13,9 @@ #include -#define FSCAPINTS 9 +#include + +#define FSCAPINTS FEATURESET_NR_ENTRIES #define NCAPINTS (FSCAPINTS + 1) /* N 32-bit words worth of info */ /* Other features, Linux-defined mapping, FSMAX+1 */ diff --git a/xen/tools/gen-cpuid.py b/xen/tools/gen-cpuid.py new file mode 100755 index 0000000..c8240c0 --- /dev/null +++ b/xen/tools/gen-cpuid.py @@ -0,0 +1,191 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import sys, os, re + +class Fail(Exception): + pass + +class State(object): + + def __init__(self, input, output): + + self.source = input + self.input = open_file_or_fd(input, "r", 2) + self.output = open_file_or_fd(output, "w", 2) + + # State parsed from input + self.names = {} # Name => value mapping + + # State calculated + self.nr_entries = 0 # Number of words in a featureset + +def parse_definitions(state): + """ + Parse featureset information from @param f and mutate the global + namespace with symbols + """ + feat_regex = re.compile( + r"^#define X86_FEATURE_([A-Z0-9_]+)" + "\s+\(([\s\d]+\*[\s\d]+\+[\s\d]+)\).*$") + + this = sys.modules[__name__] + + for l in state.input.readlines(): + # Short circuit the regex... + if not l.startswith("#define X86_FEATURE_"): + continue + + res = feat_regex.match(l) + + if res is None: + raise Fail("Failed to interpret '%s'" % (l.strip(), )) + + name = res.groups()[0] + val = eval(res.groups()[1]) # Regex confines this to a very simple expression + + if hasattr(this, name): + raise Fail("Duplicate symbol %s" % (name,)) + + if val in state.names: + raise Fail("Aliased value between %s and %s" % + (name, state.names[val])) + + # Mutate the current namespace to insert a feature literal with its + # bit index + setattr(this, name, val) + + # Construct a reverse mapping of value to name + state.names[val] = name + + +def featureset_to_uint32s(fs, nr): + """ Represent a featureset as a list of C-compatible uint32_t's """ + + bitmap = 0L + for f in fs: + bitmap |= 1L << f + + words = [] + while bitmap: + words.append(bitmap & ((1L << 32) - 1)) + bitmap >>= 32 + + assert len(words) <= nr + + if len(words) < nr: + words.extend([0] * (nr - len(words))) + + return [ "0x%08xU" % x for x in words ] + +def format_uint32s(words, indent): + """ Format a list of uint32_t's sutable for a macro definition """ + spaces = " " * indent + return spaces + (", \\\n" + spaces).join(words) + ", \\" + + +def crunch_numbers(state): + + # Size of bitmaps + state.nr_entries = nr_entries = (max(state.names.keys()) >> 5) + 1 + + +def write_results(state): + state.output.write( +"""/* + * Automatically generated by %s - Do not edit! + * Source data: %s + */ +#ifndef __XEN_X86__FEATURESET_DATA__ +#define __XEN_X86__FEATURESET_DATA__ +""" % (sys.argv[0], state.source)) + + state.output.write( +""" +#define FEATURESET_NR_ENTRIES %s +""" % (state.nr_entries, + )) + + state.output.write( +""" +#endif /* __XEN_X86__FEATURESET_DATA__ */ +""") + + +def open_file_or_fd(val, mode, buffering): + """ + If 'val' looks like a decimal integer, open it as an fd. If not, try to + open it as a regular file. + """ + + fd = -1 + try: + # Does it look like an integer? + try: + fd = int(val, 10) + except ValueError: + pass + + if fd == 0: + return sys.stdin + elif fd == 1: + return sys.stdout + elif fd == 2: + return sys.stderr + + # Try to open it... + if fd != -1: + return os.fdopen(fd, mode, buffering) + else: + return open(val, mode, buffering) + + except StandardError, e: + if fd != -1: + raise Fail("Unable to open fd %d: %s: %s" % + (fd, e.__class__.__name__, e)) + else: + raise Fail("Unable to open file '%s': %s: %s" % + (val, e.__class__.__name__, e)) + + raise SystemExit(2) + +def main(): + from optparse import OptionParser + + # Change stdout to be line-buffered. + sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 1) + + parser = OptionParser(usage = "%prog [options] -i INPUT -o OUTPUT", + description = + "Process featureset information") + + parser.add_option("-i", "--in", dest = "fin", metavar = "", + default = "0", + help = "Featureset definitions") + parser.add_option("-o", "--out", dest = "fout", metavar = "", + default = "1", + help = "Featureset calculated information") + + opts, _ = parser.parse_args() + + if opts.fin is None or opts.fout is None: + parser.print_help(sys.stderr) + raise SystemExit(1) + + state = State(opts.fin, opts.fout) + + parse_definitions(state) + crunch_numbers(state) + write_results(state) + + +if __name__ == "__main__": + try: + sys.exit(main()) + except Fail, e: + print >>sys.stderr, e + sys.exit(1) + except SystemExit, e: + sys.exit(e.code) + except KeyboardInterrupt: + sys.exit(2)