[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 |