|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |