[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v4 04/34] HYPERCALL_version_op. New hypercall mirroring XENVER_ but sane.
On Mon, Mar 21, 2016 at 06:45:28AM -0600, Jan Beulich wrote: > >>> On 18.03.16 at 20:22, <konrad.wilk@xxxxxxxxxx> wrote: > >> > + * return the number of bytes requested for the operation. Or an > >> > + * negative value if an error is encountered. > >> > + */ > >> > + > >> > +typedef uint64_t xen_version_op_val_t; > >> > +DEFINE_XEN_GUEST_HANDLE(xen_version_op_val_t); > >> > + > >> > +typedef void xen_version_op_buf_t; > >> > +DEFINE_XEN_GUEST_HANDLE(xen_version_op_buf_t); > >> > >> Are these actually useful for anything? And for the various strings, > > > > The xen_version_op_val_t is definitly used by the toolstack. > > > >> wouldn't a "char" handle be more natural? > > > > Heh. It was char[] before but Andrew liked it as void. > > But that was because you used it for non string types too, > wasn't it? Yes. For the build-id which is a binary blob. And as you noticed - also the domain handle which can be anything. > > > @@ -380,6 +388,133 @@ DO(xen_version)(int cmd, XEN_GUEST_HANDLE_PARAM(void) > > arg) > > return -ENOSYS; > > } > > > > +static const char *capabilities_info(unsigned int *len) > > +{ > > + static xen_capabilities_info_t __read_mostly cached_cap; > > + static unsigned int __read_mostly cached_cap_len; > > + static bool_t cached; > > + > > + if ( unlikely(!cached) ) > > + { > > + arch_get_xen_caps(&cached_cap); > > + cached_cap_len = strlen(cached_cap) + 1; > > + cached = 1; > > + } > > I'm sorry for noticing this only now, but without any locking this is > unsafe: x86's arch_get_xen_caps() using safe_strcat() to fill the > buffer, simultaneous invocations would possibly produce garbled > output to all (i.e. also subsequently started) guests. Either use a > real lock here, or make the guard a tristate one, which gets > transitioned e.g. from 0 to -1 by the first one coming here (doing > the initialization), with everyone else waiting for it to become +1 > (to which the initializing party sets it once it is done). That would indeed be bad. What if an _init_ code called this to 'pre-cache' it? > > > +DO(version_op)(unsigned int cmd, XEN_GUEST_HANDLE_PARAM(void) arg, > > + unsigned int len) > > +{ > > + union { > > + xen_version_op_val_t val; > > + xen_feature_info_t fi; > > + } u = {}; > > + unsigned int sz = 0; > > + const void *ptr = NULL; > > + int rc = xsm_version_op(XSM_OTHER, cmd); > > + > > + /* We can safely return -EPERM! */ > > + if ( rc ) > > + return rc; > > + > > + /* > > + * The HYPERVISOR_xen_version differs in that some return the value, > > + * and some copy it on back on argument. We follow the same rule for > > all > > + * sub-ops: return 0 on success, positive value of bytes returned, and > > + * always copy the result in arg. Yeey sanity! > > + */ > > + switch ( cmd ) > > + { > > + case XEN_VERSION_version: > > + sz = sizeof(xen_version_op_val_t); > > + u.val = (xen_major_version() << 16) | xen_minor_version(); > > + break; > > + > > + case XEN_VERSION_extraversion: > > + sz = strlen(xen_extra_version()) + 1; > > + ptr = xen_extra_version(); > > + break; > > + > > + case XEN_VERSION_capabilities: > > + ptr = capabilities_info(&sz); > > + break; > > + > > + case XEN_VERSION_changeset: > > + sz = strlen(xen_changeset()) + 1; > > + ptr = xen_changeset(); > > + break; > > + > > + case XEN_VERSION_platform_parameters: > > + sz = sizeof(xen_version_op_val_t); > > + u.val = HYPERVISOR_VIRT_START; > > + break; > > + > > + case XEN_VERSION_get_features: > > + if ( copy_from_guest(&u.fi, arg, 1) ) > > Afaict this is incompatible with the null handle check further down (i.e. > you also need to check for a null handle here). Oh my. Indeed. > > > --- a/xen/include/public/arch-arm.h > > +++ b/xen/include/public/arch-arm.h > > @@ -128,6 +128,9 @@ > > * * VCPUOP_register_vcpu_info > > * * VCPUOP_register_runstate_memory_area > > * > > + * HYPERVISOR_version_op > > + * All generic sub-operations > > + * > > * > > * Other notes on the ARM ABI: > > I don't think the extra almost blank line is warranted here. > > > --- a/xen/include/public/version.h > > +++ b/xen/include/public/version.h > > @@ -30,7 +30,15 @@ > > > > #include "xen.h" > > > > -/* NB. All ops return zero on success, except XENVER_{version,pagesize} */ > > +/* > > + * There are two hypercalls mentioned in here. The XENVER_ are for > > + * HYPERCALL_xen_version (17), while VERSION_ are for the > > + * HYPERCALL_version_op (41). > > + * > > + * The subops are very similar except that the later hypercall has a > > + * sane interface. > > + */ > > + > > > > /* arg == NULL; returns major:minor (16:16). */ > > Nor is the extra blank one here. > > > @@ -87,6 +95,66 @@ typedef struct xen_feature_info xen_feature_info_t; > > #define XENVER_commandline 9 > > typedef char xen_commandline_t[1024]; > > > > + > > + > > +/* > > + * The HYPERCALL_version_op has a set of sub-ops which mirror the > > And three consecutive blank lines are too much in any event. (If > for no other reason that because that provides extremely bad > patch context if a later change happened right next to these three > lines.) > > > +/* > > + * arg == char. > > + * > > + * The toolstack fills it out for guest consumption. It is intended to hold > > + * the UUID of the guest. > > + */ > > +#define XEN_VERSION_guest_handle 8 > > So this is the place where I agree with Andrew char is not an > appropriate type. A void or uint8 handle seems like what you > want here. /me nods. > > > --- a/xen/include/xsm/dummy.h > > +++ b/xen/include/xsm/dummy.h > > @@ -751,3 +751,22 @@ static XSM_INLINE int xsm_xen_version (XSM_DEFAULT_ARG > > uint32_t op) > > return xsm_default_action(XSM_PRIV, current->domain, NULL); > > } > > } > > + > > +static XSM_INLINE int xsm_version_op (XSM_DEFAULT_ARG uint32_t op) > > +{ > > + XSM_ASSERT_ACTION(XSM_OTHER); > > + switch ( op ) > > + { > > + case XEN_VERSION_version: > > + case XEN_VERSION_extraversion: > > + case XEN_VERSION_capabilities: > > + case XEN_VERSION_platform_parameters: > > + case XEN_VERSION_get_features: > > + case XEN_VERSION_pagesize: > > + case XEN_VERSION_guest_handle: > > + /* These MUST always be accessible to any guest by default. */ > > + return xsm_default_action(XSM_HOOK, current->domain, NULL); > > + default: > > + return xsm_default_action(XSM_PRIV, current->domain, NULL); > > Considering that we seem to have settled on some exceptions here > for the change adding XSM check to the legacy version op, do you > really think going with no exception at all here is the right approach? > Because if we do, that'll prevent guests getting fully converted over > to the new interface. Of course, we could also make this conversion > specifically a non-goal, and omit e.g. XEN_VERSION_VERSION from > this new interface. No no. I think convesion is the right long-term goal. However the nice thing about this hypercall is that it can return -EPERM. Making it always return an value for XEN_VERSION_version, XEN_VERSION_platform_parameters, XEN_VERSION_get_features means that there are some exceptions to this "can return -EPERM" as they will be guaranteed an postive return value. They can ignore the -EPERM case. And means that guest can still take shortcuts. I agree with you that guests need these hypercalls but at the same time I am not sure what can be done so they don't fall flat on their faces if they are presented with -EPERM. The Linux xenbus_init can be modified to deal with this returning -EPERM where it makes some assumptions. But in a likelyhood it is the bad assumption! Andrew, what do you think? > > Jan _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |