[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 06/13] libx86: Introduce a helper to serialise a cpuid_policy object
The serialised form is made up of the leaf, subleaf and data tuple. As this is the architectural form, it is expected not to change going forwards. x86_cpuid_copy_to_buffer() is implemented using Xen's regular copy_to_guest primitives, with an API-compatible memcpy() is used for the libxc half of the build. Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx> --- CC: Jan Beulich <JBeulich@xxxxxxxx> CC: Wei Liu <wei.liu2@xxxxxxxxxx> CC: Roger Pau Monné <roger.pau@xxxxxxxxxx> CC: Sergey Dyasli <sergey.dyasli@xxxxxxxxxx> CC: Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx> --- xen/common/libx86/cpuid.c | 94 ++++++++++++++++++++++++++++++++++++++ xen/common/libx86/libx86-private.h | 17 +++++++ xen/include/public/arch-x86/xen.h | 11 +++++ xen/include/xen/libx86/cpuid.h | 25 ++++++++++ 4 files changed, 147 insertions(+) diff --git a/xen/common/libx86/cpuid.c b/xen/common/libx86/cpuid.c index 9fa7d95..d38c505 100644 --- a/xen/common/libx86/cpuid.c +++ b/xen/common/libx86/cpuid.c @@ -34,6 +34,100 @@ const uint32_t *x86_cpuid_lookup_deep_deps(uint32_t feature) } /* + * Copy a single cpuid_leaf into a provided xen_cpuid_leaf_t buffer, + * performing boundary checking against the buffer size. + */ +static int copy_leaf_to_buffer(uint32_t leaf, uint32_t subleaf, + const struct cpuid_leaf *data, + cpuid_leaf_buffer_t leaves, + uint32_t *curr_entry, const uint32_t nr_entries) +{ + const xen_cpuid_leaf_t val = { + leaf, subleaf, data->a, data->b, data->c, data->d, + }; + + if ( *curr_entry == nr_entries ) + return -ENOBUFS; + + if ( copy_to_buffer_offset(leaves, *curr_entry, &val, 1) ) + return -EFAULT; + + ++*curr_entry; + + return 0; +} + +/* + * Serialise a cpuid_policy object into an array. Writes at most + * CPUID_MAX_SERIALISED_LEAVES. On success, nr_entries_p is updated with the + * actual number of leaves written. + */ +int x86_cpuid_copy_to_buffer(const struct cpuid_policy *p, + cpuid_leaf_buffer_t leaves, + uint32_t *nr_entries_p) +{ + const uint32_t nr_entries = *nr_entries_p; + uint32_t curr_entry = 0, leaf, subleaf; + +#define COPY_LEAF(l, s, data) \ + ({ int ret; \ + if ( (ret = copy_leaf_to_buffer( \ + l, s, data, leaves, &curr_entry, nr_entries)) ) \ + return ret; \ + }) + + /* Basic leaves. */ + for ( leaf = 0; leaf <= MIN(p->basic.max_leaf, + ARRAY_SIZE(p->basic.raw) - 1); ++leaf ) + { + switch ( leaf ) + { + case 0x4: + for ( subleaf = 0; subleaf < ARRAY_SIZE(p->cache.raw); ++subleaf ) + COPY_LEAF(leaf, subleaf, &p->cache.raw[subleaf]); + break; + + case 0x7: + for ( subleaf = 0; + subleaf <= MIN(p->feat.max_subleaf, + ARRAY_SIZE(p->feat.raw) - 1); ++subleaf ) + COPY_LEAF(leaf, subleaf, &p->feat.raw[subleaf]); + break; + + case 0xb: + for ( subleaf = 0; subleaf < ARRAY_SIZE(p->topo.raw); ++subleaf ) + COPY_LEAF(leaf, subleaf, &p->topo.raw[subleaf]); + break; + + case 0xd: + for ( subleaf = 0; subleaf < ARRAY_SIZE(p->xstate.raw); ++subleaf ) + COPY_LEAF(leaf, subleaf, &p->xstate.raw[subleaf]); + break; + + default: + COPY_LEAF(leaf, XEN_CPUID_NO_SUBLEAF, &p->basic.raw[leaf]); + break; + } + } + + COPY_LEAF(0x40000000, XEN_CPUID_NO_SUBLEAF, + &(struct cpuid_leaf){ p->hv_limit }); + COPY_LEAF(0x40000100, XEN_CPUID_NO_SUBLEAF, + &(struct cpuid_leaf){ p->hv2_limit }); + + /* Extended leaves. */ + for ( leaf = 0; leaf <= MIN(p->extd.max_leaf & 0xfffful, + ARRAY_SIZE(p->extd.raw) - 1); ++leaf ) + COPY_LEAF(0x80000000 | leaf, XEN_CPUID_NO_SUBLEAF, &p->extd.raw[leaf]); + +#undef COPY_LEAF + + *nr_entries_p = curr_entry; + + return 0; +} + +/* * Local variables: * mode: C * c-file-style: "BSD" diff --git a/xen/common/libx86/libx86-private.h b/xen/common/libx86/libx86-private.h index b9f42f7..a209850 100644 --- a/xen/common/libx86/libx86-private.h +++ b/xen/common/libx86/libx86-private.h @@ -8,8 +8,13 @@ #include <xen/lib.h> #include <xen/types.h> +#include <asm/guest_access.h> + +#define copy_to_buffer_offset copy_to_guest_offset + #else +#include <errno.h> #include <inttypes.h> #include <stdbool.h> #include <stddef.h> @@ -17,6 +22,7 @@ #include <xen-tools/libs.h> #define MAX(x, y) ((x) > (y) ? (x) : (y)) +#define MIN(x, y) ((x) < (y) ? (x) : (y)) #define ARRAY_SIZE(x) (sizeof x / sizeof *x) @@ -27,6 +33,17 @@ static inline bool test_bit(unsigned int bit, const void *vaddr) return addr[bit / 8] & (1u << (bit % 8)); } +/* memcpy(), but with copy_to_guest_offset()'s API */ +#define copy_to_buffer_offset(dst, index, src, nr) ({ \ + const typeof(*(dst)) *s = (src); \ + unsigned int i; \ + \ + for ( i = 0; i < (nr); i++ ) \ + (dst)[(index) + i] = s[i]; \ + \ + 0; \ +}) + #endif /* __XEN__ */ #endif /* XEN_LIBX86_PRIVATE_H */ diff --git a/xen/include/public/arch-x86/xen.h b/xen/include/public/arch-x86/xen.h index 69ee4bc..f3bdd83 100644 --- a/xen/include/public/arch-x86/xen.h +++ b/xen/include/public/arch-x86/xen.h @@ -314,6 +314,17 @@ struct xen_arch_domainconfig { #define XEN_ACPI_GPE0_CPUHP_BIT 2 #endif +/* + * Representations of architectural CPUID information. Used as the + * serialised version of Xen's internal representation. + */ +typedef struct xen_cpuid_leaf { +#define XEN_CPUID_NO_SUBLEAF 0xffffffffu + uint32_t leaf, subleaf; + uint32_t a, b, c, d; +} xen_cpuid_leaf_t; +DEFINE_XEN_GUEST_HANDLE(xen_cpuid_leaf_t); + #endif /* !__ASSEMBLY__ */ /* diff --git a/xen/include/xen/libx86/cpuid.h b/xen/include/xen/libx86/cpuid.h index 233fa13..48ce48d 100644 --- a/xen/include/xen/libx86/cpuid.h +++ b/xen/include/xen/libx86/cpuid.h @@ -30,6 +30,19 @@ struct cpuid_leaf #define CPUID_GUEST_NR_EXTD MAX(CPUID_GUEST_NR_EXTD_INTEL, \ CPUID_GUEST_NR_EXTD_AMD) +/* + * Maximum number of leaves a struct cpuid_policy turns into when serialised + * for interaction with the toolstack. (Sum of all leaves in each union, less + * the entries in basic which sub-unions hang off of.) + */ +#define CPUID_MAX_SERIALISED_LEAVES \ + (CPUID_GUEST_NR_BASIC + \ + CPUID_GUEST_NR_FEAT - !!CPUID_GUEST_NR_FEAT + \ + CPUID_GUEST_NR_CACHE - !!CPUID_GUEST_NR_CACHE + \ + CPUID_GUEST_NR_TOPO - !!CPUID_GUEST_NR_TOPO + \ + CPUID_GUEST_NR_XSTATE - !!CPUID_GUEST_NR_XSTATE + \ + CPUID_GUEST_NR_EXTD + 2 /* hv_limit and hv2_limit */ ) + struct cpuid_policy { #define DECL_BITFIELD(word) _DECL_BITFIELD(FEATURESET_ ## word) @@ -230,6 +243,18 @@ static inline void cpuid_featureset_to_policy( const uint32_t *x86_cpuid_lookup_deep_deps(uint32_t feature); +#ifdef __XEN__ +#include <public/arch-x86/xen.h> +typedef XEN_GUEST_HANDLE_64(xen_cpuid_leaf_t) cpuid_leaf_buffer_t; +#else +#include <xen/arch-x86/xen.h> +typedef xen_cpuid_leaf_t *cpuid_leaf_buffer_t; +#endif + +int x86_cpuid_copy_to_buffer(const struct cpuid_policy *p, + cpuid_leaf_buffer_t leaves, + uint32_t *nr_entries_p); + #endif /* !XEN_LIBX86_CPUID_H */ /* -- 2.1.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |