diff mbox series

[11/21] libs/guest: allow updating a cpu policy CPUID data

Message ID 20210323095849.37858-12-roger.pau@citrix.com (mailing list archive)
State Superseded
Headers show
Series libs/guest: new CPUID/MSR interface | expand

Commit Message

Roger Pau Monné March 23, 2021, 9:58 a.m. UTC
Introduce a helper to update the CPUID policy using an array of
xen_cpuid_leaf_t entries. Note the leaves present in the input
xen_cpuid_leaf_t array will replace any existing leaves on the policy.

No user of the interface introduced on this patch.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
---
 tools/include/xenctrl.h         |  3 ++
 tools/libs/guest/xg_cpuid_x86.c | 67 +++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+)

Comments

Jan Beulich March 30, 2021, 3:56 p.m. UTC | #1
On 23.03.2021 10:58, Roger Pau Monne wrote:
> --- a/tools/libs/guest/xg_cpuid_x86.c
> +++ b/tools/libs/guest/xg_cpuid_x86.c
> @@ -966,3 +966,70 @@ int xc_cpu_policy_get_msr(xc_interface *xch, const xc_cpu_policy_t policy,
>      free(msrs);
>      return rc;
>  }
> +
> +int xc_cpu_policy_update_cpuid(xc_interface *xch, xc_cpu_policy_t policy,
> +                               const xen_cpuid_leaf_t *leaves,
> +                               uint32_t nr)
> +{
> +    unsigned int err_leaf = -1, err_subleaf = -1;
> +    unsigned int nr_leaves, nr_msrs, i, j;
> +    xen_cpuid_leaf_t *current;
> +    int rc = xc_cpu_policy_get_size(xch, &nr_leaves, &nr_msrs);
> +
> +    if ( rc )
> +    {
> +        PERROR("Failed to obtain policy info size");
> +        return -1;
> +    }
> +
> +    current = calloc(nr_leaves, sizeof(*current));
> +    if ( !current )
> +    {
> +        PERROR("Failed to allocate resources");
> +        errno = ENOMEM;
> +        return -1;
> +    }
> +
> +    rc = xc_cpu_policy_serialise(xch, policy, current, &nr_leaves, NULL, 0);
> +    if ( rc )
> +        goto out;
> +
> +    for ( i = 0; i < nr; i++ )
> +    {
> +        const xen_cpuid_leaf_t *update = &leaves[i];
> +
> +        for ( j = 0; j < nr_leaves; j++ )
> +            if ( current[j].leaf == update->leaf &&
> +                 current[j].subleaf == update->subleaf )
> +            {
> +                /*
> +                 * NB: cannot use an assignation because of the const vs
> +                 * non-const difference.
> +                 */
> +                memcpy(&current[j], update, sizeof(*update));

I'm having trouble understanding the comment. In

    current[j] = *update;

the lvalue is xen_cpuid_leaf_t and the rvalue is const xen_cpuid_leaf_t.
That the usual (and permitted) arrangement afaics.

Jan
Roger Pau Monné March 31, 2021, 12:47 p.m. UTC | #2
On Tue, Mar 30, 2021 at 05:56:35PM +0200, Jan Beulich wrote:
> On 23.03.2021 10:58, Roger Pau Monne wrote:
> > --- a/tools/libs/guest/xg_cpuid_x86.c
> > +++ b/tools/libs/guest/xg_cpuid_x86.c
> > @@ -966,3 +966,70 @@ int xc_cpu_policy_get_msr(xc_interface *xch, const xc_cpu_policy_t policy,
> >      free(msrs);
> >      return rc;
> >  }
> > +
> > +int xc_cpu_policy_update_cpuid(xc_interface *xch, xc_cpu_policy_t policy,
> > +                               const xen_cpuid_leaf_t *leaves,
> > +                               uint32_t nr)
> > +{
> > +    unsigned int err_leaf = -1, err_subleaf = -1;
> > +    unsigned int nr_leaves, nr_msrs, i, j;
> > +    xen_cpuid_leaf_t *current;
> > +    int rc = xc_cpu_policy_get_size(xch, &nr_leaves, &nr_msrs);
> > +
> > +    if ( rc )
> > +    {
> > +        PERROR("Failed to obtain policy info size");
> > +        return -1;
> > +    }
> > +
> > +    current = calloc(nr_leaves, sizeof(*current));
> > +    if ( !current )
> > +    {
> > +        PERROR("Failed to allocate resources");
> > +        errno = ENOMEM;
> > +        return -1;
> > +    }
> > +
> > +    rc = xc_cpu_policy_serialise(xch, policy, current, &nr_leaves, NULL, 0);
> > +    if ( rc )
> > +        goto out;
> > +
> > +    for ( i = 0; i < nr; i++ )
> > +    {
> > +        const xen_cpuid_leaf_t *update = &leaves[i];
> > +
> > +        for ( j = 0; j < nr_leaves; j++ )
> > +            if ( current[j].leaf == update->leaf &&
> > +                 current[j].subleaf == update->subleaf )
> > +            {
> > +                /*
> > +                 * NB: cannot use an assignation because of the const vs
> > +                 * non-const difference.
> > +                 */
> > +                memcpy(&current[j], update, sizeof(*update));
> 
> I'm having trouble understanding the comment. In
> 
>     current[j] = *update;
> 
> the lvalue is xen_cpuid_leaf_t and the rvalue is const xen_cpuid_leaf_t.
> That the usual (and permitted) arrangement afaics.

I'm sure I was doing something really stupid, and as a bonus I failed
to properly parse the error message I got from the compiler. It's now
fixed here and below.

Thanks, Roger.
Andrew Cooper April 1, 2021, 2:55 p.m. UTC | #3
On 23/03/2021 09:58, Roger Pau Monne wrote:
> diff --git a/tools/libs/guest/xg_cpuid_x86.c b/tools/libs/guest/xg_cpuid_x86.c
> index 091aeb70c9c..13c2972ccd3 100644
> --- a/tools/libs/guest/xg_cpuid_x86.c
> +++ b/tools/libs/guest/xg_cpuid_x86.c
> @@ -966,3 +966,70 @@ int xc_cpu_policy_get_msr(xc_interface *xch, const xc_cpu_policy_t policy,
>      free(msrs);
>      return rc;
>  }
> +
> +int xc_cpu_policy_update_cpuid(xc_interface *xch, xc_cpu_policy_t policy,
> +                               const xen_cpuid_leaf_t *leaves,
> +                               uint32_t nr)
> +{
> +    unsigned int err_leaf = -1, err_subleaf = -1;
> +    unsigned int nr_leaves, nr_msrs, i, j;
> +    xen_cpuid_leaf_t *current;
> +    int rc = xc_cpu_policy_get_size(xch, &nr_leaves, &nr_msrs);
> +
> +    if ( rc )
> +    {
> +        PERROR("Failed to obtain policy info size");
> +        return -1;
> +    }
> +
> +    current = calloc(nr_leaves, sizeof(*current));
> +    if ( !current )
> +    {
> +        PERROR("Failed to allocate resources");
> +        errno = ENOMEM;
> +        return -1;
> +    }
> +
> +    rc = xc_cpu_policy_serialise(xch, policy, current, &nr_leaves, NULL, 0);
> +    if ( rc )
> +        goto out;
> +
> +    for ( i = 0; i < nr; i++ )
> +    {
> +        const xen_cpuid_leaf_t *update = &leaves[i];
> +
> +        for ( j = 0; j < nr_leaves; j++ )
> +            if ( current[j].leaf == update->leaf &&
> +                 current[j].subleaf == update->subleaf )
> +            {
> +                /*
> +                 * NB: cannot use an assignation because of the const vs
> +                 * non-const difference.
> +                 */
> +                memcpy(&current[j], update, sizeof(*update));
> +                break;
> +            }
> +
> +        if ( j == nr_leaves )
> +        {
> +            /* Failed to find a matching leaf, append to the end. */
> +            current = realloc(current, (nr_leaves + 1) * sizeof(*current));
> +            memcpy(&current[nr_leaves], update, sizeof(*update));
> +            nr_leaves++;
> +        }
> +    }
> +
> +    rc = x86_cpuid_copy_from_buffer(policy->cpuid, current, nr_leaves,
> +                                    &err_leaf, &err_subleaf);

Why do you need any earlier logic?  x86_cpuid_copy_from_buffer() already
does exactly this operation.

~Andrew
diff mbox series

Patch

diff --git a/tools/include/xenctrl.h b/tools/include/xenctrl.h
index ab34df1dc98..2143478fe4b 100644
--- a/tools/include/xenctrl.h
+++ b/tools/include/xenctrl.h
@@ -2613,6 +2613,9 @@  int xc_cpu_policy_get_cpuid(xc_interface *xch, const xc_cpu_policy_t policy,
                             xen_cpuid_leaf_t *out);
 int xc_cpu_policy_get_msr(xc_interface *xch, const xc_cpu_policy_t policy,
                           uint32_t msr, xen_msr_entry_t *out);
+int xc_cpu_policy_update_cpuid(xc_interface *xch, xc_cpu_policy_t policy,
+                               const xen_cpuid_leaf_t *leaves,
+                               uint32_t nr);
 
 int xc_get_cpu_levelling_caps(xc_interface *xch, uint32_t *caps);
 int xc_get_cpu_featureset(xc_interface *xch, uint32_t index,
diff --git a/tools/libs/guest/xg_cpuid_x86.c b/tools/libs/guest/xg_cpuid_x86.c
index 091aeb70c9c..13c2972ccd3 100644
--- a/tools/libs/guest/xg_cpuid_x86.c
+++ b/tools/libs/guest/xg_cpuid_x86.c
@@ -966,3 +966,70 @@  int xc_cpu_policy_get_msr(xc_interface *xch, const xc_cpu_policy_t policy,
     free(msrs);
     return rc;
 }
+
+int xc_cpu_policy_update_cpuid(xc_interface *xch, xc_cpu_policy_t policy,
+                               const xen_cpuid_leaf_t *leaves,
+                               uint32_t nr)
+{
+    unsigned int err_leaf = -1, err_subleaf = -1;
+    unsigned int nr_leaves, nr_msrs, i, j;
+    xen_cpuid_leaf_t *current;
+    int rc = xc_cpu_policy_get_size(xch, &nr_leaves, &nr_msrs);
+
+    if ( rc )
+    {
+        PERROR("Failed to obtain policy info size");
+        return -1;
+    }
+
+    current = calloc(nr_leaves, sizeof(*current));
+    if ( !current )
+    {
+        PERROR("Failed to allocate resources");
+        errno = ENOMEM;
+        return -1;
+    }
+
+    rc = xc_cpu_policy_serialise(xch, policy, current, &nr_leaves, NULL, 0);
+    if ( rc )
+        goto out;
+
+    for ( i = 0; i < nr; i++ )
+    {
+        const xen_cpuid_leaf_t *update = &leaves[i];
+
+        for ( j = 0; j < nr_leaves; j++ )
+            if ( current[j].leaf == update->leaf &&
+                 current[j].subleaf == update->subleaf )
+            {
+                /*
+                 * NB: cannot use an assignation because of the const vs
+                 * non-const difference.
+                 */
+                memcpy(&current[j], update, sizeof(*update));
+                break;
+            }
+
+        if ( j == nr_leaves )
+        {
+            /* Failed to find a matching leaf, append to the end. */
+            current = realloc(current, (nr_leaves + 1) * sizeof(*current));
+            memcpy(&current[nr_leaves], update, sizeof(*update));
+            nr_leaves++;
+        }
+    }
+
+    rc = x86_cpuid_copy_from_buffer(policy->cpuid, current, nr_leaves,
+                                    &err_leaf, &err_subleaf);
+    if ( rc )
+    {
+        ERROR("Failed to deserialise CPUID (err leaf %#x, subleaf %#x) (%d = %s)",
+              err_leaf, err_subleaf, -rc, strerror(-rc));
+        errno = -rc;
+        rc = -1;
+    }
+
+ out:
+    free(current);
+    return rc;
+}