[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH RFC] x86/sysctl: Implement XEN_SYSCTL_get_cpuid_policy
>>> Andrew Cooper <andrew.cooper3@xxxxxxxxxx> 07/27/17 7:48 PM >>> >@@ -599,6 +600,93 @@ int init_domain_cpuid_policy(struct domain *d) >return 0; >} > >+/* >+ * Copy a single cpuid_leaf into a guest-provided xen_cpuid_leaf_t buffer, >+ * performing boundary checking against the guests array size. >+ */ >+static int copy_leaf_to_guest(uint32_t leaf, uint32_t subleaf, >+ const struct cpuid_leaf *data, >+ XEN_GUEST_HANDLE_64(xen_cpuid_leaf_t) leaves, >+ uint32_t *curr_leaf, uint32_t nr_leaves) >+{ >+ const xen_cpuid_leaf_t val = >+ { leaf, subleaf, data->a, data->b, data->c, data->d }; >+ >+ if ( copy_to_guest_offset(leaves, *curr_leaf, &val, 1) ) >+ return -EFAULT; >+ >+ if ( ++(*curr_leaf) == nr_leaves ) >+ return -ENOBUFS; Why? Either check before copying, or prevent returning an error when this last entry precisely fit into the last provided slot. In particular ... >+int copy_cpuid_policy_to_guest(const struct cpuid_policy *p, >+ XEN_GUEST_HANDLE_64(xen_cpuid_leaf_t) leaves, >+ uint32_t *nr_leaves_p) >+{ >+ uint32_t nr_leaves = *nr_leaves_p, curr_leaf = 0, leaf, subleaf; >+ >+ if ( nr_leaves == 0 ) >+ return -ENOBUFS; ... such an explicit check should not be needed. >+#define COPY_LEAF(l, s, data) \ >+ ({ int ret; /* Elide leaves which are fully empty. */ \ >+ if ( (*(uint64_t *)(&(data)->a) | \ >+ *(uint64_t *)(&(data)->c)) && \ This sort of casting looks rather fragile. >--- a/xen/arch/x86/sysctl.c >+++ b/xen/arch/x86/sysctl.c >@@ -250,6 +250,42 @@ long arch_do_sysctl( >break; >} > >+ case XEN_SYSCTL_get_cpuid_policy: >+ { >+ static const struct cpuid_policy *const policy_table[] = { >+ [XEN_SYSCTL_cpuid_policy_raw] = &raw_cpuid_policy, >+ [XEN_SYSCTL_cpuid_policy_host] = &host_cpuid_policy, >+ }; >+ const struct cpuid_policy *p = NULL; >+ >+ /* Request for maximum number of leaves? */ >+ if ( guest_handle_is_null(sysctl->u.cpuid_policy.policy) ) >+ { >+ sysctl->u.cpuid_policy.nr_leaves = CPUID_MAX_SERIALISED_LEAVES; >+ if ( __copy_field_to_guest(u_sysctl, sysctl, >+ u.cpuid_policy.nr_leaves) ) >+ ret = -EFAULT; Couldn't this be folded with the other copy operation below, at once ... >+ break; >+ } >+ >+ /* Look up requested policy. */ >+ if ( sysctl->u.cpuid_policy.index < ARRAY_SIZE(policy_table) ) >+ p = policy_table[sysctl->u.cpuid_policy.index]; >+ >+ /* Bad policy index? */ >+ if ( !p ) >+ ret = -EINVAL; >+ else >+ ret = copy_cpuid_policy_to_guest(p, sysctl->u.cpuid_policy.policy, >+ >&sysctl->u.cpuid_policy.nr_leaves); >+ >+ /* Inform the caller of how many leaves we wrote. */ >+ if ( !ret ) >+ ret = __copy_field_to_guest(u_sysctl, sysctl, >+ u.cpuid_policy.nr_leaves); ... avoiding to return other than -EFAULT if the copying fails? >--- a/xen/include/asm-x86/cpuid.h >+++ b/xen/include/asm-x86/cpuid.h >@@ -70,6 +70,18 @@ DECLARE_PER_CPU(bool, cpuid_faulting_enabled); >#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_XSTATE - !!CPUID_GUEST_NR_XSTATE + \ >+ CPUID_GUEST_NR_EXTD) Why these strange !! uses? Can't you just say "- 1", as these counts all are non-zero anyway? >--- a/xen/include/public/domctl.h >+++ b/xen/include/public/domctl.h >@@ -692,6 +692,14 @@ struct xen_domctl_cpuid { >}; >typedef struct xen_domctl_cpuid xen_domctl_cpuid_t; >DEFINE_XEN_GUEST_HANDLE(xen_domctl_cpuid_t); >+ >+#define XEN_CPUID_NO_SUBLEAF 0xffffffffu What if some leaf gains a subleaf with this index? >+struct xen_cpuid_leaf { >+ uint32_t leaf, subleaf; >+ uint32_t a, b, c, d; In the public interface I'd prefer eax etc. Also I assume you place this in domctl.h because of anticipated use by a future domctl? Jan _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |