|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 3/9] x86/cpuid: Extend the cpuid= command line option to support all named features
For gen-cpuid.py, fix a comment describing self.names, and generate the
reverse mapping in self.values. Write out INIT_FEATURE_NAMES which maps a
string name to a bit position.
For parse_cpuid(), introduce a slightly fuzzy strcmp() to accept changes in
punctuation, and perform a binary search over INIT_FEATURE_NAMES.
Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
CC: Jan Beulich <JBeulich@xxxxxxxx>
CC: Wei Liu <wei.liu2@xxxxxxxxxx>
CC: Roger Pau Monné <roger.pau@xxxxxxxxxx>
Slightly RFC, because I'm not entirely certain if this is a good idea or not.
---
xen/arch/x86/cpuid.c | 91 ++++++++++++++++++++++++++++++++++++--------------
xen/tools/gen-cpuid.py | 22 ++++++++++--
2 files changed, 86 insertions(+), 27 deletions(-)
diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
index 0591a7d..eb86a86 100644
--- a/xen/arch/x86/cpuid.c
+++ b/xen/arch/x86/cpuid.c
@@ -18,9 +18,34 @@ 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;
+/*
+ * Works like strcmp(), but customised specifically for this usecase. 'name'
+ * is a NUL terminated string. 's' is considered to match 'name' if the NUL
+ * terminator of 'name' match punctiation in 's'.
+ */
+static int __init cpuid_name_cmp(const char *s, const char *name)
+{
+ int res;
+
+ /* Basic strcmp(). */
+ for ( ; *name != '\0'; ++name, ++s )
+ if ( (res = (*s - *name)) != 0 )
+ break;
+
+ /* If a failure, but only because '=' or ',', override to success. */
+ if ( res && *name == '\0' && (*s == '=' || *s == ',') )
+ res = 0;
+
+ return res;
+}
+
static int __init parse_xen_cpuid(const char *s)
{
- const char *ss;
+ static const struct feature {
+ const char *name;
+ unsigned int bit;
+ } features[] __initconst = INIT_FEATURE_NAMES, *lhs, *mid, *rhs;
+ const char *ss, *feat;
int val, rc = 0;
do {
@@ -28,32 +53,48 @@ static int __init parse_xen_cpuid(const char *s)
if ( !ss )
ss = strchr(s, '\0');
- if ( (val = parse_boolean("ibpb", s, ss)) >= 0 )
- {
- if ( !val )
- setup_clear_cpu_cap(X86_FEATURE_IBPB);
- }
- else if ( (val = parse_boolean("ibrsb", s, ss)) >= 0 )
- {
- if ( !val )
- setup_clear_cpu_cap(X86_FEATURE_IBRSB);
- }
- else if ( (val = parse_boolean("stibp", s, ss)) >= 0 )
- {
- if ( !val )
- setup_clear_cpu_cap(X86_FEATURE_STIBP);
- }
- else if ( (val = parse_boolean("l1d-flush", s, ss)) >= 0 )
- {
- if ( !val )
- setup_clear_cpu_cap(X86_FEATURE_L1D_FLUSH);
- }
- else if ( (val = parse_boolean("ssbd", s, ss)) >= 0 )
+ /* Skip the 'no-' prefix for name comparisons. */
+ feat = s;
+ if ( strncmp(s, "no-", 3) == 0 )
+ feat += 3;
+
+ /* (Re)initalise lhs and rhs for binary search. */
+ lhs = features;
+ rhs = features + ARRAY_SIZE(features);
+
+ while ( lhs < rhs )
{
- if ( !val )
- setup_clear_cpu_cap(X86_FEATURE_SSBD);
+ int res;
+
+ mid = lhs + (rhs - lhs) / 2;
+ res = cpuid_name_cmp(feat, mid->name);
+
+ if ( res < 0 )
+ {
+ rhs = mid;
+ continue;
+ }
+ if ( res > 0 )
+ {
+ lhs = mid + 1;
+ continue;
+ }
+
+ if ( (val = parse_boolean(mid->name, s, ss)) >= 0 )
+ {
+ if ( !val )
+ setup_clear_cpu_cap(mid->bit);
+ mid = NULL;
+ }
+
+ break;
}
- else
+
+ /*
+ * Mid being NULL means that the name search failed, or that
+ * parse_boolean() failed.
+ */
+ if ( mid )
rc = -EINVAL;
s = ss + 1;
diff --git a/xen/tools/gen-cpuid.py b/xen/tools/gen-cpuid.py
index 27569bd..002de6f 100755
--- a/xen/tools/gen-cpuid.py
+++ b/xen/tools/gen-cpuid.py
@@ -19,7 +19,8 @@ class State(object):
self.output = open_file_or_fd(output, "w", 2)
# State parsed from input
- self.names = {} # Name => value mapping
+ self.names = {} # Value => Name mapping
+ self.values = {} # Name => Value mapping
self.raw_special = set()
self.raw_pv = set()
self.raw_hvm_shadow = set()
@@ -76,8 +77,9 @@ def parse_definitions(state):
this_name = name
setattr(this, this_name, val)
- # Construct a reverse mapping of value to name
+ # Construct forward and reverse mappings between name and value
state.names[val] = name
+ state.values[name.lower().replace("_", "-")] = val
for a in attr:
@@ -393,6 +395,22 @@ def write_results(state):
state.output.write(
"""}
+#define INIT_FEATURE_NAMES { \\
+""")
+
+ try:
+ _tmp = state.values.iteritems()
+ except AttributeError:
+ _tmp = state.values.items()
+
+ for name, bit in sorted(_tmp):
+ state.output.write(
+ ' { "%s", %sU },\\\n' % (name, bit)
+ )
+
+ state.output.write(
+"""}
+
""")
for idx, text in enumerate(state.bitfields):
--
2.1.4
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |