libxl: split logic to parse user provided CPUID features

Move the CPUID value parsers out of libxl_cpuid_parse_config() into a
newly created cpuid_add() local helper.  This is in preparation for
also adding MSR feature parsing support.

No functional change intended.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>
(cherry picked from commit e2b1da9b8f)
This commit is contained in:
Roger Pau Monne authored and Andrew Cooper committed 2023-08-08 16:02:17 +01:00
1 parent 48a0a355b0
commit a27d2bfb5c
1 file changed
+63 -57
+63 -57
View File
@@ -96,6 +96,66 @@ static struct xc_xend_cpuid *cpuid_find_match(libxl_cpuid_policy_list *pl,
return *list + i;
}
static int cpuid_add(libxl_cpuid_policy_list *policy,
const struct cpuid_flags *flag, const char *val)
{
struct xc_xend_cpuid *entry = cpuid_find_match(policy, flag->leaf,
flag->subleaf);
unsigned long num;
char flags[33], *resstr, *endptr;
unsigned int i;
resstr = entry->policy[flag->reg - 1];
num = strtoul(val, &endptr, 0);
flags[flag->length] = 0;
if (endptr != val) {
/* if this was a valid number, write the binary form into the string */
for (i = 0; i < flag->length; i++) {
flags[flag->length - 1 - i] = "01"[(num >> i) & 1];
}
} else {
switch(val[0]) {
case 'x': case 'k': case 's':
memset(flags, val[0], flag->length);
break;
default:
return 3;
}
}
if (resstr == NULL) {
resstr = strdup("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
}
/* the family and model entry is potentially split up across
* two fields in Fn0000_0001_EAX, so handle them here separately.
*/
if (!strcmp(flag->name, "family")) {
if (num < 16) {
memcpy(resstr + (32 - 4) - flag->bit, flags + 4, 4);
memcpy(resstr + (32 - 8) - 20, "00000000", 8);
} else {
num -= 15;
memcpy(resstr + (32 - 4) - flag->bit, "1111", 4);
for (i = 0; i < 7; i++) {
flags[7 - i] = "01"[num & 1];
num >>= 1;
}
memcpy(resstr + (32 - 8) - 20, flags, 8);
}
} else if (!strcmp(flag->name, "model")) {
memcpy(resstr + (32 - 4) - 16, flags, 4);
memcpy(resstr + (32 - 4) - flag->bit, flags + 4, 4);
} else {
memcpy(resstr + (32 - flag->length) - flag->bit, flags,
flag->length);
}
entry->policy[flag->reg - 1] = resstr;
return 0;
}
/* parse a single key=value pair and translate it into the libxc
* used interface using 32-characters strings for each register.
* Will overwrite earlier entries and thus can be called multiple
@@ -332,12 +392,8 @@ int libxl_cpuid_parse_config(libxl_cpuid_policy_list *policy, const char* str)
{NULL, 0, NA, CPUID_REG_INV, 0, 0}
};
#undef NA
char *sep, *val, *endptr;
int i;
const char *sep, *val;
const struct cpuid_flags *flag;
struct xc_xend_cpuid *entry;
unsigned long num;
char flags[33], *resstr;
sep = strchr(str, '=');
if (sep == NULL) {
@@ -347,60 +403,10 @@ int libxl_cpuid_parse_config(libxl_cpuid_policy_list *policy, const char* str)
}
for (flag = cpuid_flags; flag->name != NULL; flag++) {
if(!strncmp(str, flag->name, sep - str) && flag->name[sep - str] == 0)
break;
}
if (flag->name == NULL) {
return 2;
}
entry = cpuid_find_match(policy, flag->leaf, flag->subleaf);
resstr = entry->policy[flag->reg - 1];
num = strtoull(val, &endptr, 0);
flags[flag->length] = 0;
if (endptr != val) {
/* if this was a valid number, write the binary form into the string */
for (i = 0; i < flag->length; i++) {
flags[flag->length - 1 - i] = "01"[!!(num & (1 << i))];
}
} else {
switch(val[0]) {
case 'x': case 'k': case 's':
memset(flags, val[0], flag->length);
break;
default:
return 3;
}
return cpuid_add(policy, flag, val);
}
if (resstr == NULL) {
resstr = strdup("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
}
/* the family and model entry is potentially split up across
* two fields in Fn0000_0001_EAX, so handle them here separately.
*/
if (!strncmp(str, "family", sep - str)) {
if (num < 16) {
memcpy(resstr + (32 - 4) - flag->bit, flags + 4, 4);
memcpy(resstr + (32 - 8) - 20, "00000000", 8);
} else {
num -= 15;
memcpy(resstr + (32 - 4) - flag->bit, "1111", 4);
for (i = 0; i < 7; i++) {
flags[7 - i] = "01"[num & 1];
num >>= 1;
}
memcpy(resstr + (32 - 8) - 20, flags, 8);
}
} else if (!strncmp(str, "model", sep - str)) {
memcpy(resstr + (32 - 4) - 16, flags, 4);
memcpy(resstr + (32 - 4) - flag->bit, flags + 4, 4);
} else {
memcpy(resstr + (32 - flag->length) - flag->bit, flags,
flag->length);
}
entry->policy[flag->reg - 1] = resstr;
return 0;
return 2;
}
/* parse a single list item from the legacy Python xend syntax, where
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.