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:
Andrew Cooper committed 2019-09-06 17:16:22 +01:00
1 parent 71946aa528
commit 7479151106
4 files changed
+72 -36

No files matched your search

+47 -29
View File
@@ -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
View File
@@ -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;
+2 -2
View File
@@ -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
View File
@@ -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):
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.