|
[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 |