@@ -2635,6 +2635,10 @@ int xc_cpu_policy_make_compatible(xc_interface *xch, xc_cpu_policy_t policy,
int xc_cpu_policy_topology(xc_interface *xch, xc_cpu_policy_t policy,
bool hvm);
+/* Apply an xc_xend_cpuid object to the policy. */
+int xc_cpu_policy_apply_cpuid(xc_interface *xch, xc_cpu_policy_t policy,
+ const struct xc_xend_cpuid *cpuid, bool hvm);
+
int xc_get_cpu_levelling_caps(xc_interface *xch, uint32_t *caps);
int xc_get_cpu_featureset(xc_interface *xch, uint32_t index,
uint32_t *nr_features, uint32_t *featureset);
@@ -258,144 +258,107 @@ static int set_domain_cpu_policy(xc_interface *xch, uint32_t domid,
return ret;
}
-static int compare_leaves(const void *l, const void *r)
-{
- const xen_cpuid_leaf_t *lhs = l;
- const xen_cpuid_leaf_t *rhs = r;
-
- if ( lhs->leaf != rhs->leaf )
- return lhs->leaf < rhs->leaf ? -1 : 1;
-
- if ( lhs->subleaf != rhs->subleaf )
- return lhs->subleaf < rhs->subleaf ? -1 : 1;
-
- return 0;
-}
-
-static xen_cpuid_leaf_t *find_leaf(
- xen_cpuid_leaf_t *leaves, unsigned int nr_leaves,
- const struct xc_xend_cpuid *xend)
-{
- const xen_cpuid_leaf_t key = { xend->leaf, xend->subleaf };
-
- return bsearch(&key, leaves, nr_leaves, sizeof(*leaves), compare_leaves);
-}
-
-static int xc_cpuid_xend_policy(
- xc_interface *xch, uint32_t domid, const struct xc_xend_cpuid *xend)
+int xc_cpu_policy_apply_cpuid(xc_interface *xch, xc_cpu_policy_t policy,
+ const struct xc_xend_cpuid *cpuid, bool hvm)
{
int rc;
- xc_dominfo_t di;
- unsigned int nr_leaves, nr_msrs;
- uint32_t err_leaf = -1, err_subleaf = -1, err_msr = -1;
- /*
- * Three full policies. The host, domain max, and domain current for the
- * domain type.
- */
- xen_cpuid_leaf_t *host = NULL, *max = NULL, *cur = NULL;
- unsigned int nr_host, nr_max, nr_cur;
+ xc_cpu_policy_t host = NULL, max = NULL;
- if ( xc_domain_getinfo(xch, domid, 1, &di) != 1 ||
- di.domid != domid )
- {
- ERROR("Failed to obtain d%d info", domid);
- rc = -ESRCH;
- goto fail;
- }
-
- rc = xc_cpu_policy_get_size(xch, &nr_leaves, &nr_msrs);
- if ( rc )
- {
- PERROR("Failed to obtain policy info size");
- rc = -errno;
- goto fail;
- }
-
- rc = -ENOMEM;
- if ( (host = calloc(nr_leaves, sizeof(*host))) == NULL ||
- (max = calloc(nr_leaves, sizeof(*max))) == NULL ||
- (cur = calloc(nr_leaves, sizeof(*cur))) == NULL )
- {
- ERROR("Unable to allocate memory for %u CPUID leaves", nr_leaves);
- goto fail;
- }
-
- /* Get the domain's current policy. */
- nr_msrs = 0;
- nr_cur = nr_leaves;
- rc = get_domain_cpu_policy(xch, domid, &nr_cur, cur, &nr_msrs, NULL);
- if ( rc )
+ host = xc_cpu_policy_init();
+ max = xc_cpu_policy_init();
+ if ( !host || !max )
{
- PERROR("Failed to obtain d%d current policy", domid);
- rc = -errno;
- goto fail;
+ PERROR("Failed to init policies");
+ rc = -ENOMEM;
+ goto out;
}
/* Get the domain's max policy. */
- nr_msrs = 0;
- nr_max = nr_leaves;
- rc = get_system_cpu_policy(xch, di.hvm ? XEN_SYSCTL_cpu_policy_hvm_max
+ rc = xc_cpu_policy_get_system(xch, hvm ? XEN_SYSCTL_cpu_policy_hvm_max
: XEN_SYSCTL_cpu_policy_pv_max,
- &nr_max, max, &nr_msrs, NULL);
+ max);
if ( rc )
{
- PERROR("Failed to obtain %s max policy", di.hvm ? "hvm" : "pv");
- rc = -errno;
- goto fail;
+ PERROR("Failed to obtain %s max policy", hvm ? "hvm" : "pv");
+ goto out;
}
/* Get the host policy. */
- nr_msrs = 0;
- nr_host = nr_leaves;
- rc = get_system_cpu_policy(xch, XEN_SYSCTL_cpu_policy_host,
- &nr_host, host, &nr_msrs, NULL);
+ rc = xc_cpu_policy_get_system(xch, XEN_SYSCTL_cpu_policy_host, host);
if ( rc )
{
PERROR("Failed to obtain host policy");
- rc = -errno;
- goto fail;
+ goto out;
}
rc = -EINVAL;
- for ( ; xend->leaf != XEN_CPUID_INPUT_UNUSED; ++xend )
+ for ( ; cpuid->leaf != XEN_CPUID_INPUT_UNUSED; ++cpuid )
{
- xen_cpuid_leaf_t *cur_leaf = find_leaf(cur, nr_cur, xend);
- const xen_cpuid_leaf_t *max_leaf = find_leaf(max, nr_max, xend);
- const xen_cpuid_leaf_t *host_leaf = find_leaf(host, nr_host, xend);
+ xen_cpuid_leaf_t cur_leaf;
+ xen_cpuid_leaf_t max_leaf;
+ xen_cpuid_leaf_t host_leaf;
- if ( cur_leaf == NULL || max_leaf == NULL || host_leaf == NULL )
+ rc = xc_cpu_policy_get_cpuid(xch, policy, cpuid->leaf, cpuid->subleaf,
+ &cur_leaf);
+ if ( rc )
+ {
+ ERROR("Failed to get current policy leaf %#x subleaf %#x",
+ cpuid->leaf, cpuid->subleaf);
+ goto out;
+ }
+ rc = xc_cpu_policy_get_cpuid(xch, max, cpuid->leaf, cpuid->subleaf,
+ &max_leaf);
+ if ( rc )
{
- ERROR("Missing leaf %#x, subleaf %#x", xend->leaf, xend->subleaf);
- goto fail;
+ ERROR("Failed to get max policy leaf %#x subleaf %#x",
+ cpuid->leaf, cpuid->subleaf);
+ goto out;
+ }
+ rc = xc_cpu_policy_get_cpuid(xch, host, cpuid->leaf, cpuid->subleaf,
+ &host_leaf);
+ if ( rc )
+ {
+ ERROR("Failed to get host policy leaf %#x subleaf %#x",
+ cpuid->leaf, cpuid->subleaf);
+ goto out;
}
- for ( unsigned int i = 0; i < ARRAY_SIZE(xend->policy); i++ )
+ for ( unsigned int i = 0; i < ARRAY_SIZE(cpuid->policy); i++ )
{
- uint32_t *cur_reg = &cur_leaf->a + i;
- const uint32_t *max_reg = &max_leaf->a + i;
- const uint32_t *host_reg = &host_leaf->a + i;
+ uint32_t *cur_reg = &cur_leaf.a + i;
+ const uint32_t *max_reg = &max_leaf.a + i;
+ const uint32_t *host_reg = &host_leaf.a + i;
- if ( xend->policy[i] == NULL )
+ if ( cpuid->policy[i] == NULL )
continue;
for ( unsigned int j = 0; j < 32; j++ )
{
bool val;
- if ( xend->policy[i][j] == '1' )
+ switch ( cpuid->policy[i][j] )
+ {
+ case '1':
val = true;
- else if ( xend->policy[i][j] == '0' )
+ break;
+
+ case '0':
val = false;
- else if ( xend->policy[i][j] == 'x' )
+ break;
+
+ case 'x':
val = test_bit(31 - j, max_reg);
- else if ( xend->policy[i][j] == 'k' ||
- xend->policy[i][j] == 's' )
+ break;
+
+ case 'k':
+ case 's':
val = test_bit(31 - j, host_reg);
- else
- {
+ break;
+
+ default:
ERROR("Bad character '%c' in policy[%d] string '%s'",
- xend->policy[i][j], i, xend->policy[i]);
- goto fail;
+ cpuid->policy[i][j], i, cpuid->policy[i]);
+ goto out;
}
clear_bit(31 - j, cur_reg);
@@ -403,25 +366,19 @@ static int xc_cpuid_xend_policy(
set_bit(31 - j, cur_reg);
}
}
- }
- /* Feed the transformed currrent policy back up to Xen. */
- rc = set_domain_cpu_policy(xch, domid, nr_cur, cur, 0, NULL,
- &err_leaf, &err_subleaf, &err_msr);
- if ( rc )
- {
- PERROR("Failed to set d%d's policy (err leaf %#x, subleaf %#x, msr %#x)",
- domid, err_leaf, err_subleaf, err_msr);
- rc = -errno;
- goto fail;
+ rc = xc_cpu_policy_update_cpuid(xch, policy, &cur_leaf, 1);
+ if ( rc )
+ {
+ PERROR("Failed to set policy leaf %#x subleaf %#x",
+ cpuid->leaf, cpuid->subleaf);
+ goto out;
+ }
}
- /* Success! */
-
- fail:
- free(cur);
- free(max);
- free(host);
+ out:
+ xc_cpu_policy_destroy(max);
+ xc_cpu_policy_destroy(host);
return rc;
}
@@ -429,7 +386,7 @@ static int xc_cpuid_xend_policy(
int xc_cpuid_apply_policy(xc_interface *xch, uint32_t domid, bool restore,
const uint32_t *featureset, unsigned int nr_features,
bool pae, bool itsc, bool nested_virt,
- const struct xc_xend_cpuid *xend)
+ const struct xc_xend_cpuid *cpuid)
{
int rc;
xc_dominfo_t di;
@@ -551,6 +508,10 @@ int xc_cpuid_apply_policy(xc_interface *xch, uint32_t domid, bool restore,
if ( rc )
goto out;
+ rc = xc_cpu_policy_apply_cpuid(xch, &policy, cpuid, di.hvm);
+ if ( rc )
+ goto out;
+
rc = x86_cpuid_copy_to_buffer(p, leaves, &nr_leaves);
if ( rc )
{
@@ -568,9 +529,6 @@ int xc_cpuid_apply_policy(xc_interface *xch, uint32_t domid, bool restore,
goto out;
}
- if ( xend && (rc = xc_cpuid_xend_policy(xch, domid, xend)) )
- goto out;
-
rc = 0;
out:
Rename xc_cpuid_xend_policy to xc_cpu_policy_apply_cpuid and make it public. Modify the function internally to use the new xc_cpu_policy_* set of functions. Also don't apply the passed policy to a domain directly, and instead modify the provided xc_cpu_policy_t. The caller will be responsible of applying the modified cpu policy to the domain. Note that further patches will end up removing this function, since the parsing of a cpu policy in xend format is a layering violation, now the callers should have the necessary helpers to modify an xc_cpu_policy_t themselves. No functional change intended. Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> --- tools/include/xenctrl.h | 4 + tools/libs/guest/xg_cpuid_x86.c | 200 +++++++++++++------------------- 2 files changed, 83 insertions(+), 121 deletions(-)