All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andrew Cooper <andrew.cooper3@citrix.com>
To: Xen-devel <xen-devel@lists.xen.org>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>,
	Ian Jackson <Ian.Jackson@eu.citrix.com>,
	Ian Campbell <Ian.Campbell@citrix.com>,
	Jan Beulich <JBeulich@suse.com>, Wei Liu <wei.liu2@citrix.com>
Subject: [PATCH RFC 15/31] x86: Generate deep dependencies of x86 features
Date: Wed, 16 Dec 2015 21:24:17 +0000	[thread overview]
Message-ID: <1450301073-28191-16-git-send-email-andrew.cooper3@citrix.com> (raw)
In-Reply-To: <1450301073-28191-1-git-send-email-andrew.cooper3@citrix.com>

Some features depend on other features.  Working out and maintaining the exact
dependency tree is complicated, so it is expressed in script form instead.

`gen-feature-deps.py` parses 'xen/include/public/arch-x86/featureset.h' (To
obtain some literal names conforming to the API), contains some single-step
dependency information, performs some number crunching, and writes autogen.c
to make the results of the number crunching available.

In this case, it writes out deep dependency infomarion, to allow featureset
code to find all eventual features cleared in a dependency chain.

To be able to compile for userspace, libxc's bitmap macros are made more
generic (to match Xen's), and accept a void * instead of unsigned long *.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Ian Campbell <Ian.Campbell@citrix.com>
CC: Ian Jackson <Ian.Jackson@eu.citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>

TODO: The generation of autogen.c now means that libxc needs to be compiled
after the hypervisor, as the vpath doesn't convey the generation information.
I need to find a way to fix this.
---
 .gitignore                             |   1 +
 tools/libxc/Makefile                   |   2 +-
 tools/libxc/xc_bitops.h                |  12 +--
 xen/arch/x86/cpuid/Makefile            |   5 ++
 xen/arch/x86/cpuid/cpuid-private.h     |  18 ++++
 xen/arch/x86/cpuid/cpuid.c             |  28 ++++++
 xen/arch/x86/cpuid/gen-feature-deps.py | 152 +++++++++++++++++++++++++++++++++
 7 files changed, 211 insertions(+), 7 deletions(-)
 create mode 100755 xen/arch/x86/cpuid/gen-feature-deps.py

diff --git a/.gitignore b/.gitignore
index 63944b5..f757164 100644
--- a/.gitignore
+++ b/.gitignore
@@ -228,6 +228,7 @@ xen/arch/x86/xen.lds
 xen/arch/x86/boot/reloc.S
 xen/arch/x86/boot/reloc.bin
 xen/arch/x86/boot/reloc.lnk
+xen/arch/x86/cpuid/autogen.c
 xen/arch/x86/efi.lds
 xen/arch/x86/efi/check.efi
 xen/arch/x86/efi/disabled
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
index 83547e1..7c8c2d8 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -82,7 +82,7 @@ $(patsubst %.c,%.opic,$(ELF_SRCS-y)): CFLAGS += -Wno-pointer-sign
 ifeq ($(CONFIG_X86),y)
 vpath %.c ../../xen/arch/x86/cpuid
 CFLAGS += -I../../xen/arch/x86/cpuid
-CTRL_SRCS-y += cpuid.c
+CTRL_SRCS-y += cpuid.c autogen.c
 endif
 
 # new domain builder
diff --git a/tools/libxc/xc_bitops.h b/tools/libxc/xc_bitops.h
index cd749f4..8e645a1 100644
--- a/tools/libxc/xc_bitops.h
+++ b/tools/libxc/xc_bitops.h
@@ -36,19 +36,19 @@ static inline void bitmap_clear(unsigned long *addr, int nr_bits)
     memset(addr, 0, bitmap_size(nr_bits));
 }
 
-static inline int test_bit(int nr, unsigned long *addr)
+static inline int test_bit(int nr, const void *addr)
 {
-    return (BITMAP_ENTRY(nr, addr) >> BITMAP_SHIFT(nr)) & 1;
+    return (BITMAP_ENTRY(nr, (const unsigned long *)addr) >> BITMAP_SHIFT(nr)) & 1;
 }
 
-static inline void clear_bit(int nr, unsigned long *addr)
+static inline void clear_bit(int nr, void *addr)
 {
-    BITMAP_ENTRY(nr, addr) &= ~(1UL << BITMAP_SHIFT(nr));
+    BITMAP_ENTRY(nr, (unsigned long *)addr) &= ~(1UL << BITMAP_SHIFT(nr));
 }
 
-static inline void set_bit(int nr, unsigned long *addr)
+static inline void set_bit(int nr, void *addr)
 {
-    BITMAP_ENTRY(nr, addr) |= (1UL << BITMAP_SHIFT(nr));
+    BITMAP_ENTRY(nr, (unsigned long *)addr) |= (1UL << BITMAP_SHIFT(nr));
 }
 
 static inline int test_and_clear_bit(int nr, unsigned long *addr)
diff --git a/xen/arch/x86/cpuid/Makefile b/xen/arch/x86/cpuid/Makefile
index 3fb2e0b..0fb720a 100644
--- a/xen/arch/x86/cpuid/Makefile
+++ b/xen/arch/x86/cpuid/Makefile
@@ -1 +1,6 @@
 obj-y += cpuid.o
+obj-y += autogen.o
+
+autogen.c: gen-feature-deps.py
+	$(PYTHON) gen-feature-deps.py
+	$(call move-if-changed,autogen.c.tmp,autogen.c)
diff --git a/xen/arch/x86/cpuid/cpuid-private.h b/xen/arch/x86/cpuid/cpuid-private.h
index 1c92ee4..438f5d2 100644
--- a/xen/arch/x86/cpuid/cpuid-private.h
+++ b/xen/arch/x86/cpuid/cpuid-private.h
@@ -64,6 +64,24 @@ extern const uint32_t pv_featuremask[XEN_NR_FEATURESET_ENTRIES];
 extern const uint32_t hvm_shadow_featuremask[XEN_NR_FEATURESET_ENTRIES];
 extern const uint32_t hvm_hap_featuremask[XEN_NR_FEATURESET_ENTRIES];
 
+/* A featureset with a tag. */
+struct tagged_featureset
+{
+    uint32_t tag;
+    uint32_t fs[XEN_NR_FEATURESET_ENTRIES];
+};
+
+/* Sparse feature matrix identifying all features which depend on a feature. */
+extern const struct tagged_featureset deep_deps[];
+
+/* Number of entries in deep_deps. */
+extern const unsigned int nr_deep_deps;
+
+/* Bitmap of each tag found in 'deep_deps'. */
+extern const uint32_t deep_dep_features[XEN_NR_FEATURESET_ENTRIES];
+
+const struct tagged_featureset *lookup_deep_deps(uint32_t feature);
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/arch/x86/cpuid/cpuid.c b/xen/arch/x86/cpuid/cpuid.c
index 25385d4..20c36f7 100644
--- a/xen/arch/x86/cpuid/cpuid.c
+++ b/xen/arch/x86/cpuid/cpuid.c
@@ -300,6 +300,34 @@ const uint32_t hvm_hap_featuremask[XEN_NR_FEATURESET_ENTRIES] =
 };
 
 /*
+ * Looks up a features deep dependency.  Returns a pointer, or NULL if not
+ * found.
+ */
+const struct tagged_featureset *lookup_deep_deps(uint32_t feat)
+{
+    unsigned int start = 0, end = nr_deep_deps;
+
+    /* Fast early exit. */
+    if ( !test_bit(feat, deep_dep_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].tag > feat )
+            end = mid;
+        else if ( deep_deps[mid].tag < feat )
+            start = mid + 1;
+        else
+            return &deep_deps[mid];
+    }
+
+    return NULL;
+}
+
+/*
  * Local variables:
  * mode: C
  * c-file-style: "BSD"
diff --git a/xen/arch/x86/cpuid/gen-feature-deps.py b/xen/arch/x86/cpuid/gen-feature-deps.py
new file mode 100755
index 0000000..f0ecbba
--- /dev/null
+++ b/xen/arch/x86/cpuid/gen-feature-deps.py
@@ -0,0 +1,152 @@
+#!/usr/bin/env python
+import sys, os, os.path as path, re
+
+names = {}
+
+with open(path.join(os.environ["XEN_ROOT"],
+                    "xen/include/public/arch-x86/featureset.h")) as f:
+
+    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 f.readlines():
+        # Short circuit the regex...
+        if not l.startswith("#define X86_FEATURE_"):
+            continue
+
+        res = feat_regex.match(l)
+
+        if res is None:
+            print >>sys.stderr, "Failed to interpret '%s'" % (l, )
+            sys.exit(1)
+
+        name = res.groups()[0]
+        val = eval(res.groups()[1]) # Regex confines this to a very simple expression
+
+        # Expected duplicate symbols.  Discard
+        if name in ('3DNOW_ALT', ):
+            continue
+
+        if hasattr(this, name) or val in names:
+            print >>sys.stderr, "Duplicate symbol or representation for '%s'" \
+                % (name, )
+            sys.exit(1)
+
+        # 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
+        names[val] = name
+
+
+# Dependences specified as a dictionary of tuples: The feature in the key
+# is a direct dependency of each of the features in the tuple.
+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()))
+
+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:
+            print >>sys.stderr, "ERROR: Cycle found with %s when processing %s" \
+                % (names[f], names[feat])
+            sys.exit(1)
+
+        seen.append(f)
+        to_process.extend(deps.get(f, []))
+
+    deep_deps[feat] = seen[1:]
+
+def format_featurset(fs):
+
+    words = {}
+    res = "\n"
+
+    # Identify which featureset words each feature resides in
+    for f in fs:
+        word = f >> 5
+
+        if word in words:
+            words[word].append(f)
+        else:
+            words[word] = [f]
+
+    for w in sorted(words.keys()):
+        wf = sorted(words[w])
+
+        res += "        [cpufeat_word(X86_FEATURE_%s)] = (\n" % (names[wf[0]], )
+
+        res += " |\n".join(
+            "            cpufeat_mask(X86_FEATURE_%s)" %
+            (names[f], ) for f in wf)
+
+        res += "),\n\n"
+
+    return res.rstrip()
+
+with open(path.join(os.environ["XEN_ROOT"],
+                    "xen/arch/x86/cpuid/autogen.c.tmp"), "w") as f:
+    f.write(
+"""/*
+ * Automatically generated by %s - Do not edit!
+ */
+#include "cpuid-private.h"
+
+const struct tagged_featureset deep_deps[] =
+{""" % (sys.argv[0],))
+
+    for d in sorted(deep_deps.keys()):
+        f.write("""
+    { X86_FEATURE_%s,
+      {%s
+      }
+    },
+""" % (names[d], format_featurset(deep_deps[d])))
+
+    f.write(
+"""};
+
+const unsigned int nr_deep_deps = ARRAY_SIZE(deep_deps);
+
+const uint32_t deep_dep_features[XEN_NR_FEATURESET_ENTRIES] =
+{%s
+};
+""" % (format_featurset(deep_features), ))
-- 
2.1.4

  parent reply	other threads:[~2015-12-16 21:24 UTC|newest]

Thread overview: 123+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-12-16 21:24 [PATCH RFC 00/31] x86: Improvements to cpuid handling for guests Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 01/31] xen/public: Export featureset information in the public API Andrew Cooper
2015-12-22 16:28   ` Jan Beulich
2015-12-22 16:42     ` Andrew Cooper
2015-12-22 16:59       ` Jan Beulich
2015-12-23 10:05         ` Andrew Cooper
2015-12-23 10:24           ` Jan Beulich
2015-12-23 11:26             ` Andrew Cooper
2016-01-06  7:43               ` Jan Beulich
2015-12-16 21:24 ` [PATCH RFC 02/31] tools/libxc: Use public/featureset.h for cpuid policy generation Andrew Cooper
2015-12-22 16:29   ` Jan Beulich
2016-01-05 14:13     ` Ian Campbell
2016-01-05 14:17       ` Andrew Cooper
2016-01-05 14:18         ` Ian Campbell
2016-01-05 14:23           ` Andrew Cooper
2016-01-05 15:02             ` Ian Campbell
2016-01-05 15:42               ` Andrew Cooper
2016-01-05 16:09                 ` Ian Campbell
2015-12-16 21:24 ` [PATCH RFC 03/31] xen/x86: Store antifeatures inverted in a featureset Andrew Cooper
2015-12-22 16:32   ` Jan Beulich
2015-12-22 17:03     ` Andrew Cooper
2016-01-05 14:19       ` Ian Campbell
2016-01-05 14:24         ` Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 04/31] xen/x86: Mask out unknown features from Xen's capabilities Andrew Cooper
2015-12-22 16:42   ` Jan Beulich
2015-12-22 17:01     ` Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 05/31] xen/x86: Collect more CPUID feature words Andrew Cooper
2015-12-22 16:46   ` Jan Beulich
2015-12-22 17:17     ` Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 06/31] xen/x86: Infrastructure to calculate guest featuresets Andrew Cooper
2015-12-22 16:50   ` Jan Beulich
2015-12-16 21:24 ` [PATCH RFC 07/31] xen/x86: Export host featureset via SYSCTL Andrew Cooper
2015-12-22 16:57   ` Jan Beulich
2015-12-16 21:24 ` [PATCH RFC 08/31] tools/stubs: Expose host featureset to userspace Andrew Cooper
2016-01-05 15:36   ` Ian Campbell
2016-01-05 15:59     ` Andrew Cooper
2016-01-05 16:09       ` Ian Campbell
2016-01-05 16:19         ` Andrew Cooper
2016-01-05 16:38           ` Ian Campbell
2015-12-16 21:24 ` [PATCH RFC 09/31] xen/x86: Calculate PV featureset Andrew Cooper
2015-12-22 17:07   ` Jan Beulich
2015-12-22 17:13     ` Andrew Cooper
2015-12-22 17:18       ` Jan Beulich
2015-12-16 21:24 ` [PATCH RFC 10/31] xen/x86: Calculate HVM featureset Andrew Cooper
2015-12-22 17:11   ` Jan Beulich
2015-12-22 17:21     ` Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 11/31] xen/x86: Calculate Raw featureset Andrew Cooper
2015-12-22 17:14   ` Jan Beulich
2015-12-22 17:27     ` Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 12/31] tools: Utility for dealing with featuresets Andrew Cooper
2016-01-05 15:17   ` Ian Campbell
2016-01-05 16:14     ` Andrew Cooper
2016-01-05 16:34       ` Ian Campbell
2016-01-05 17:13         ` Andrew Cooper
2016-01-05 17:37           ` Ian Campbell
2016-01-05 18:04             ` Andrew Cooper
2016-01-06 10:38               ` Ian Campbell
2016-01-06 10:40   ` Ian Campbell
2016-01-06 10:42     ` Ian Campbell
2015-12-16 21:24 ` [PATCH RFC 13/31] tools/libxc: Wire a featureset through to cpuid policy logic Andrew Cooper
2016-01-05 15:42   ` Ian Campbell
2016-01-05 16:20     ` Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 14/31] tools/libxc: Use featureset rather than guesswork Andrew Cooper
2016-01-05 15:54   ` Ian Campbell
2016-01-05 16:22     ` Andrew Cooper
2015-12-16 21:24 ` Andrew Cooper [this message]
2016-01-05 16:03   ` [PATCH RFC 15/31] x86: Generate deep dependencies of x86 features Ian Campbell
2016-01-05 16:42     ` Andrew Cooper
2016-01-05 16:54       ` Ian Campbell
2016-01-05 17:09         ` Andrew Cooper
2016-01-05 17:19           ` Ian Campbell
2015-12-16 21:24 ` [PATCH RFC 16/31] x86: Automatically generate known_features Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 17/31] xen/x86: Clear dependent features when clearing a cpu cap Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 18/31] xen/x86: Improve disabling of features which have dependencies Andrew Cooper
2016-01-21 16:48   ` Jan Beulich
2015-12-16 21:24 ` [PATCH RFC 19/31] tools/libxc: Sanitise guest featuresets Andrew Cooper
2016-01-05 16:05   ` Ian Campbell
2015-12-16 21:24 ` [PATCH RFC 20/31] x86: Improvements to in-hypervisor cpuid sanity checks Andrew Cooper
2016-01-21 17:02   ` Jan Beulich
2016-01-21 17:21     ` Andrew Cooper
2016-01-21 18:15       ` Andrew Cooper
2016-01-22  7:47         ` Jan Beulich
2016-01-22  7:45       ` Jan Beulich
2015-12-16 21:24 ` [PATCH RFC 21/31] x86/domctl: Break out logic to update domain state from cpuid information Andrew Cooper
2016-01-21 17:05   ` Jan Beulich
2016-01-21 17:08     ` Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 22/31] x86/cpu: Move set_cpumask() calls into c_early_init() Andrew Cooper
2016-01-21 17:08   ` Jan Beulich
2015-12-16 21:24 ` [PATCH RFC 23/31] xen/x86: Export cpuid levelling capabilities via SYSCTL Andrew Cooper
2016-01-21 17:23   ` Jan Beulich
2015-12-16 21:24 ` [PATCH RFC 24/31] tools/stubs: Expose host levelling capabilities to userspace Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 25/31] xen/x86: Common infrastructure for levelling context switching Andrew Cooper
2016-01-22  8:56   ` Jan Beulich
2016-01-22 10:05     ` Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 26/31] xen/x86: Rework AMD masking MSR setup Andrew Cooper
2016-01-22  9:27   ` Jan Beulich
2016-01-22 11:01     ` Andrew Cooper
2016-01-22 11:13       ` Jan Beulich
2016-01-22 13:59         ` Andrew Cooper
2016-01-22 14:12           ` Jan Beulich
2016-01-22 17:03             ` Andrew Cooper
2016-01-25 11:25               ` Jan Beulich
2015-12-16 21:24 ` [PATCH RFC 27/31] xen/x86: Rework Intel masking/faulting setup Andrew Cooper
2016-01-22  9:40   ` Jan Beulich
2016-01-22 14:09     ` Andrew Cooper
2016-01-22 14:29       ` Jan Beulich
2016-01-22 14:46         ` Andrew Cooper
2016-01-22 14:53           ` Jan Beulich
2015-12-16 21:24 ` [PATCH RFC 28/31] xen/x86: Context switch all levelling state in context_switch() Andrew Cooper
2016-01-22  9:52   ` Jan Beulich
2016-01-22 14:19     ` Andrew Cooper
2016-01-22 14:31       ` Jan Beulich
2016-01-22 14:39         ` Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 29/31] x86/pv: Provide custom cpumasks for PV domains Andrew Cooper
2016-01-22  9:56   ` Jan Beulich
2016-01-22 14:24     ` Andrew Cooper
2016-01-22 14:33       ` Jan Beulich
2016-01-22 14:42         ` Andrew Cooper
2016-01-22 14:48           ` Jan Beulich
2016-01-22 14:56             ` Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 30/31] x86/domctl: Update PV domain cpumasks when setting cpuid policy Andrew Cooper
2016-01-22 10:02   ` Jan Beulich
2015-12-16 21:24 ` [PATCH RFC 31/31] tools/libxc: Calculate xstate cpuid leaf from guest information Andrew Cooper

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1450301073-28191-16-git-send-email-andrew.cooper3@citrix.com \
    --to=andrew.cooper3@citrix.com \
    --cc=Ian.Campbell@citrix.com \
    --cc=Ian.Jackson@eu.citrix.com \
    --cc=JBeulich@suse.com \
    --cc=wei.liu2@citrix.com \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.