mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
x86/cpuid: Extend the cpuid= 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(), use cmdline_strcmp() and perform a binary search over INIT_FEATURE_NAMES. A tweak to cmdline_strcmp() is needed to break at equals signs as well. Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> Reviewed-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
1 parent
71946aa528
commit
7479151106
4 files changed
+72
-36
No files matched your search
+47
-29
@@ -25,41 +25,59 @@ static int __init parse_xen_cpuid(const char *s)
|
||||
int val, rc = 0;
|
||||
|
||||
do {
|
||||
static const struct feature {
|
||||
const char *name;
|
||||
unsigned int bit;
|
||||
} features[] __initconstrel = INIT_FEATURE_NAMES;
|
||||
const struct feature *lhs, *mid, *rhs;
|
||||
const char *feat;
|
||||
|
||||
ss = strchr(s, ',');
|
||||
if ( !ss )
|
||||
ss = strchr(s, '\0');
|
||||
|
||||
if ( (val = parse_boolean("md-clear", 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_MD_CLEAR);
|
||||
int res;
|
||||
|
||||
mid = lhs + (rhs - lhs) / 2;
|
||||
res = cmdline_strcmp(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 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 )
|
||||
{
|
||||
if ( !val )
|
||||
setup_clear_cpu_cap(X86_FEATURE_SSBD);
|
||||
}
|
||||
else
|
||||
|
||||
/*
|
||||
* Mid being NULL means that the name and boolean were successfully
|
||||
* identified. Everything else is an error.
|
||||
*/
|
||||
if ( mid )
|
||||
rc = -EINVAL;
|
||||
|
||||
s = ss + 1;
|
||||
|
||||
+3
-3
@@ -309,10 +309,10 @@ int cmdline_strcmp(const char *frag, const char *name)
|
||||
if ( res || n == '\0' )
|
||||
{
|
||||
/*
|
||||
* NUL in 'name' matching a comma, colon or semicolon in 'frag'
|
||||
* implies success.
|
||||
* NUL in 'name' matching a comma, colon, semicolon or equals in
|
||||
* 'frag' implies success.
|
||||
*/
|
||||
if ( n == '\0' && (f == ',' || f == ':' || f == ';') )
|
||||
if ( n == '\0' && (f == ',' || f == ':' || f == ';' || f == '=') )
|
||||
res = 0;
|
||||
|
||||
return res;
|
||||
|
||||
@@ -85,8 +85,8 @@ int parse_boolean(const char *name, const char *s, const char *e);
|
||||
|
||||
/**
|
||||
* Very similar to strcmp(), but will declare a match if the NUL in 'name'
|
||||
* lines up with comma, colon or semicolon in 'frag'. Designed for picking
|
||||
* exact string matches out of a delimited command line list.
|
||||
* lines up with comma, colon, semicolon or equals in 'frag'. Designed for
|
||||
* picking exact string matches out of a delimited command line list.
|
||||
*/
|
||||
int cmdline_strcmp(const char *frag, const char *name);
|
||||
|
||||
|
||||
+20
-2
@@ -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:
|
||||
|
||||
@@ -403,6 +405,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):
|
||||
|
||||