[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH 1/3] libx86: Introduce a helper to deserialise cpuid_policy objects



>>> On 04.01.19 at 16:33, <andrew.cooper3@xxxxxxxxxx> wrote:
> --- a/xen/include/xen/lib/x86/cpuid.h
> +++ b/xen/include/xen/lib/x86/cpuid.h
> @@ -319,6 +319,27 @@ typedef xen_cpuid_leaf_t cpuid_leaf_buffer_t[];
>  int x86_cpuid_copy_to_buffer(const struct cpuid_policy *policy,
>                               cpuid_leaf_buffer_t leaves, uint32_t 
> *nr_entries);
>  
> +/**
> + * Unserialise a cpuid_policy object from an array of cpuid leaves.
> + *
> + * @param policy      The cpuid_policy to unserialise into.
> + * @param leaves      The array of leaves to unserialise from.
> + * @param nr_entries  The number of entries in 'leaves'.
> + * @param err_leaf    Optional hint filled on error.
> + * @param err_subleaf Optional hint filled on error.
> + * @returns -errno
> + *
> + * Reads at most CPUID_MAX_SERIALISED_LEAVES.  May return -ERANGE if an
> + * incoming leaf is out of range of cpuid_policy, in which case the optional
> + * err_* pointers are filled to aid diagnostics.
> + *
> + * No content validation of in-range leaves is performed.
> + */
> +int x86_cpuid_copy_from_buffer(struct cpuid_policy *policy,
> +                               const cpuid_leaf_buffer_t leaves,
> +                               uint32_t nr_entries, uint32_t *err_leaf,
> +                               uint32_t *err_subleaf);
> +
>  #endif /* !XEN_LIB_X86_CPUID_H */
>  
>  /*
> diff --git a/xen/lib/x86/cpuid.c b/xen/lib/x86/cpuid.c
> index 5a3159b..7fc4148 100644
> --- a/xen/lib/x86/cpuid.c
> +++ b/xen/lib/x86/cpuid.c
> @@ -233,6 +233,112 @@ int x86_cpuid_copy_to_buffer(const struct cpuid_policy 
> *p,
>      return 0;
>  }
>  
> +int x86_cpuid_copy_from_buffer(struct cpuid_policy *p,
> +                               const cpuid_leaf_buffer_t leaves,
> +                               uint32_t nr_entries, uint32_t *err_leaf,
> +                               uint32_t *err_subleaf)
> +{
> +    unsigned int i;
> +    xen_cpuid_leaf_t data;
> +    struct cpuid_leaf *l = (void *)&data.a;

I'd find this cast a little less worrying if you used container_of(). But
even then I dislike this well hidden assumption of similar layouts
of struct cpuid_leaf and the latter parts of struct xen_cpuid_leaf.

Also it looks as if this could be a pointer to const.

> +    /*
> +     * A well formed caller is expected pass an array with leaves in order,

... expected to pass ...

> +     * and without any repetitions.  However, due to per-vendor differences,
> +     * and in the case of upgrade or levelled scenarios, we typically expect
> +     * fewer than MAX leaves to be passed.
> +     *
> +     * Detecting repeated entries is prohibitively complicated, so we don't
> +     * bother.  That said, one way or another if more than MAX leaves are
> +     * passed, something is wrong.
> +     */
> +    if ( nr_entries > CPUID_MAX_SERIALISED_LEAVES )
> +        return -E2BIG;
> +
> +    for ( i = 0; i < nr_entries; ++i )
> +    {
> +        if ( copy_from_buffer_offset(&data, leaves, i, 1) )
> +            return -EFAULT;
> +
> +        switch ( data.leaf )
> +        {
> +        case 0 ... ARRAY_SIZE(p->basic.raw) - 1:
> +            switch ( data.leaf )
> +            {
> +            case 0x4:
> +                if ( data.subleaf >= ARRAY_SIZE(p->cache.raw) )
> +                    goto out_of_range;
> +
> +                p->cache.raw[data.subleaf] = *l;

Do you not want to use array_index_nospec() here and below?

> +                break;
> +
> +            case 0x7:
> +                if ( data.subleaf >= ARRAY_SIZE(p->feat.raw) )
> +                    goto out_of_range;
> +
> +                p->feat.raw[data.subleaf] = *l;
> +                break;
> +
> +            case 0xb:
> +                if ( data.subleaf >= ARRAY_SIZE(p->topo.raw) )
> +                    goto out_of_range;
> +
> +                p->topo.raw[data.subleaf] = *l;
> +                break;
> +
> +            case 0xd:
> +                if ( data.subleaf >= ARRAY_SIZE(p->xstate.raw) )
> +                    goto out_of_range;
> +
> +                p->xstate.raw[data.subleaf] = *l;
> +                break;
> +
> +            default:
> +                if ( data.subleaf != XEN_CPUID_NO_SUBLEAF )
> +                    goto out_of_range;
> +
> +                p->basic.raw[data.leaf] = *l;
> +                break;
> +            }
> +            break;
> +
> +        case 0x40000000:
> +            if ( data.subleaf != XEN_CPUID_NO_SUBLEAF )
> +                goto out_of_range;
> +
> +            p->hv_limit = l->a;
> +            break;
> +
> +        case 0x40000100:
> +            if ( data.subleaf != XEN_CPUID_NO_SUBLEAF )
> +                goto out_of_range;
> +
> +            p->hv2_limit = l->a;
> +            break;
> +
> +        case 0x80000000 ... 0x80000000 + ARRAY_SIZE(p->extd.raw) - 1:
> +            if ( data.subleaf != XEN_CPUID_NO_SUBLEAF )
> +                goto out_of_range;
> +
> +            p->extd.raw[data.leaf & 0xffff] = *l;
> +            break;
> +
> +        default:
> +            goto out_of_range;

Any chance I could talk you into moving the label right here,
eliminating the ugly (to me at least) error handling code after
the main return point of the function?

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.