@@ -2635,6 +2635,10 @@ int xc_cpu_policy_make_compatible(xc_interface *xch, xc_cpu_policy_t policy,
int xc_cpu_policy_legacy_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);
@@ -288,124 +288,107 @@ static xen_cpuid_leaf_t *find_leaf(
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, default for the domain type,
- * and domain current.
- */
- xen_cpuid_leaf_t *host = NULL, *def = NULL, *cur = NULL;
- unsigned int nr_host, nr_def, nr_cur;
-
- 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;
- }
+ xc_cpu_policy_t host = NULL, def = NULL;
- rc = -ENOMEM;
- if ( (host = calloc(nr_leaves, sizeof(*host))) == NULL ||
- (def = calloc(nr_leaves, sizeof(*def))) == 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();
+ def = xc_cpu_policy_init();
+ if ( !host || !def )
{
- 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 type's default policy. */
- nr_msrs = 0;
- nr_def = nr_leaves;
- rc = get_system_cpu_policy(xch, di.hvm ? XEN_SYSCTL_cpu_policy_hvm_default
+ rc = xc_cpu_policy_get_system(xch, hvm ? XEN_SYSCTL_cpu_policy_hvm_default
: XEN_SYSCTL_cpu_policy_pv_default,
- &nr_def, def, &nr_msrs, NULL);
+ def);
if ( rc )
{
- PERROR("Failed to obtain %s def policy", di.hvm ? "hvm" : "pv");
- rc = -errno;
- goto fail;
+ PERROR("Failed to obtain %s def 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->leaf, xend->subleaf);
- const xen_cpuid_leaf_t *def_leaf = find_leaf(def, nr_def,
- xend->leaf, xend->subleaf);
- const xen_cpuid_leaf_t *host_leaf = find_leaf(host, nr_host, xend->leaf,
- xend->subleaf);
-
- if ( cur_leaf == NULL || def_leaf == NULL || host_leaf == NULL )
+ xen_cpuid_leaf_t cur_leaf;
+ xen_cpuid_leaf_t def_leaf;
+ xen_cpuid_leaf_t host_leaf;
+
+ rc = xc_cpu_policy_get_cpuid(xch, policy, cpuid->leaf, cpuid->subleaf,
+ &cur_leaf);
+ if ( rc )
{
- ERROR("Missing leaf %#x, subleaf %#x", xend->leaf, xend->subleaf);
- goto fail;
+ ERROR("Failed to get current policy leaf %#x subleaf %#x",
+ cpuid->leaf, cpuid->subleaf);
+ goto out;
+ }
+ rc = xc_cpu_policy_get_cpuid(xch, def, cpuid->leaf, cpuid->subleaf,
+ &def_leaf);
+ if ( rc )
+ {
+ ERROR("Failed to get def 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 *def_reg = &def_leaf->a + i;
- const uint32_t *host_reg = &host_leaf->a + i;
+ uint32_t *cur_reg = &cur_leaf.a + i;
+ const uint32_t *def_reg = &def_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, def_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);
@@ -413,25 +396,19 @@ static int xc_cpuid_xend_policy(
set_bit(31 - j, cur_reg);
}
}
- }
- /* Feed the transformed currrent policy back up to Xen. */
- rc = xc_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(def);
- free(host);
+ out:
+ xc_cpu_policy_destroy(def);
+ xc_cpu_policy_destroy(host);
return rc;
}
@@ -439,7 +416,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;
@@ -559,6 +536,10 @@ int xc_cpuid_apply_policy(xc_interface *xch, uint32_t domid, bool restore,
goto out;
*p = policy.cpuid;
+ 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 )
{
@@ -576,9 +557,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, as 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 | 182 ++++++++++++++------------------ 2 files changed, 84 insertions(+), 102 deletions(-)