diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h index 150d7271d6..a9e4dc1540 100644 --- a/tools/libxc/include/xenctrl.h +++ b/tools/libxc/include/xenctrl.h @@ -1477,7 +1477,37 @@ int xc_tbuf_set_evt_mask(xc_interface *xch, uint32_t mask); int xc_domctl(xc_interface *xch, struct xen_domctl *domctl); int xc_sysctl(xc_interface *xch, struct xen_sysctl *sysctl); -int xc_version(xc_interface *xch, int cmd, void *arg); +/** + * This function returns the size of buffer to be allocated for + * the cmd. The cmd are XEN_VERSION_*. + */ +ssize_t xc_version_len(xc_interface *xch, unsigned int cmd); + +/** + * This function retrieves the information from the version_op hypercall. + * The len is the size of the arg buffer. If arg is NULL, will not + * perform hypercall - instead will just return the size of arg + * buffer that is needed. + * + * Note that prior to Xen 4.7 this would return 0 for success and + * negative value (-1) for error (with the error in errno). In Xen 4.7 + * and later for success it will return an positive value which is the + * number of bytes copied in arg. + * + * It can also return -1 with various errno values: + * - EPERM - not permitted. + * - ENOBUFS - the len was to short, output in arg truncated. + * - ENOSYS - not implemented. + * + * @parm xch a handle to an open hypervisor interface + * @parm cmd XEN_VERSION_* value + * @param arg Pointer to xen_version_op_buf_t or xen_version_op_val_t + * @param len Size of arg + * @return size of bytes copied in arg on success, -1 on failure (and + * errno will contain the error) + * + */ +int xc_version(xc_interface *xch, unsigned int cmd, void *arg, size_t len); int xc_flask_op(xc_interface *xch, xen_flask_op_t *op); diff --git a/tools/libxc/xc_core.c b/tools/libxc/xc_core.c index d792566a99..cfeba6b7bd 100644 --- a/tools/libxc/xc_core.c +++ b/tools/libxc/xc_core.c @@ -270,42 +270,43 @@ elfnote_fill_xen_version(xc_interface *xch, *xen_version) { int rc; + xen_version_op_val_t val = 0; memset(xen_version, 0, sizeof(*xen_version)); - rc = xc_version(xch, XENVER_version, NULL); + rc = xc_version(xch, XEN_VERSION_version, &val, sizeof(val)); if ( rc < 0 ) return rc; - xen_version->major_version = rc >> 16; - xen_version->minor_version = rc & ((1 << 16) - 1); + xen_version->major_version = val >> 16; + xen_version->minor_version = val & ((1 << 16) - 1); - rc = xc_version(xch, XENVER_extraversion, - &xen_version->extra_version); + rc = xc_version(xch, XEN_VERSION_extraversion, + xen_version->extra_version, + sizeof(xen_version->extra_version)); if ( rc < 0 ) return rc; - rc = xc_version(xch, XENVER_compile_info, - &xen_version->compile_info); + rc = xc_version(xch, XEN_VERSION_capabilities, + xen_version->capabilities, + sizeof(xen_version->capabilities)); if ( rc < 0 ) return rc; - rc = xc_version(xch, - XENVER_capabilities, &xen_version->capabilities); + rc = xc_version(xch, XEN_VERSION_changeset, xen_version->changeset, + sizeof(xen_version->changeset)); if ( rc < 0 ) return rc; - rc = xc_version(xch, XENVER_changeset, &xen_version->changeset); + rc = xc_version(xch, XEN_VERSION_platform_parameters, + &xen_version->platform_parameters, + sizeof(xen_version->platform_parameters)); if ( rc < 0 ) return rc; - rc = xc_version(xch, XENVER_platform_parameters, - &xen_version->platform_parameters); + val = 0; + rc = xc_version(xch, XEN_VERSION_pagesize, &val, sizeof(val)); if ( rc < 0 ) return rc; - - rc = xc_version(xch, XENVER_pagesize, NULL); - if ( rc < 0 ) - return rc; - xen_version->pagesize = rc; + xen_version->pagesize = val; return 0; } diff --git a/tools/libxc/xc_dom_boot.c b/tools/libxc/xc_dom_boot.c index 791041b322..bbff72e429 100644 --- a/tools/libxc/xc_dom_boot.c +++ b/tools/libxc/xc_dom_boot.c @@ -112,11 +112,19 @@ int xc_dom_compat_check(struct xc_dom_image *dom) int xc_dom_boot_xen_init(struct xc_dom_image *dom, xc_interface *xch, domid_t domid) { + xen_version_op_val_t val = 0; + + if ( xc_version(xch, XEN_VERSION_version, &val, sizeof(val)) < 0 ) + { + xc_dom_panic(xch, XC_INTERNAL_ERROR, "can't get Xen version!"); + return -1; + } + dom->xen_version = val; dom->xch = xch; dom->guest_domid = domid; - dom->xen_version = xc_version(xch, XENVER_version, NULL); - if ( xc_version(xch, XENVER_capabilities, &dom->xen_caps) < 0 ) + if ( xc_version(xch, XEN_VERSION_capabilities, dom->xen_caps, + sizeof(dom->xen_caps)) < 0 ) { xc_dom_panic(xch, XC_INTERNAL_ERROR, "can't get xen capabilities"); return -1; diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c index 050216e028..9ebd1d67d3 100644 --- a/tools/libxc/xc_domain.c +++ b/tools/libxc/xc_domain.c @@ -2084,7 +2084,8 @@ int xc_map_domain_meminfo(xc_interface *xch, int domid, _di.guest_width = minfo->guest_width; /* Get page table levels (see get_platform_info() in xg_save_restore.h */ - if ( xc_version(xch, XENVER_capabilities, &xen_caps) ) + if ( xc_version(xch, XEN_VERSION_capabilities, xen_caps, + sizeof(xen_caps)) < 0 ) { PERROR("Could not get Xen capabilities (for page table levels)"); return -1; diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c index c41e43351f..631ad91fb5 100644 --- a/tools/libxc/xc_private.c +++ b/tools/libxc/xc_private.c @@ -457,58 +457,23 @@ int xc_sysctl(xc_interface *xch, struct xen_sysctl *sysctl) return do_sysctl(xch, sysctl); } -int xc_version(xc_interface *xch, int cmd, void *arg) +ssize_t xc_version_len(xc_interface *xch, unsigned int cmd) { - DECLARE_HYPERCALL_BOUNCE(arg, 0, XC_HYPERCALL_BUFFER_BOUNCE_OUT); /* Size unknown until cmd decoded */ - size_t sz; + return do_version_op(xch, cmd, NULL, 0); +} + +int xc_version(xc_interface *xch, unsigned int cmd, void *arg, size_t sz) +{ + DECLARE_HYPERCALL_BOUNCE(arg, sz, XC_HYPERCALL_BUFFER_BOUNCE_OUT); int rc; - switch ( cmd ) - { - case XENVER_version: - sz = 0; - break; - case XENVER_extraversion: - sz = sizeof(xen_extraversion_t); - break; - case XENVER_compile_info: - sz = sizeof(xen_compile_info_t); - break; - case XENVER_capabilities: - sz = sizeof(xen_capabilities_info_t); - break; - case XENVER_changeset: - sz = sizeof(xen_changeset_info_t); - break; - case XENVER_platform_parameters: - sz = sizeof(xen_platform_parameters_t); - break; - case XENVER_get_features: - sz = sizeof(xen_feature_info_t); - break; - case XENVER_pagesize: - sz = 0; - break; - case XENVER_guest_handle: - sz = sizeof(xen_domain_handle_t); - break; - case XENVER_commandline: - sz = sizeof(xen_commandline_t); - break; - default: - ERROR("xc_version: unknown command %d\n", cmd); - return -EINVAL; - } - - HYPERCALL_BOUNCE_SET_SIZE(arg, sz); - - if ( (sz != 0) && xc_hypercall_bounce_pre(xch, arg) ) + if ( xc_hypercall_bounce_pre(xch, arg) ) { PERROR("Could not bounce buffer for version hypercall"); return -ENOMEM; } - rc = do_xen_version(xch, cmd, HYPERCALL_BUFFER(arg)); + rc = do_version_op(xch, cmd, HYPERCALL_BUFFER(arg), sz); if ( sz != 0 ) xc_hypercall_bounce_post(xch, arg); diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h index aa8daf1b1c..5be8fdd64f 100644 --- a/tools/libxc/xc_private.h +++ b/tools/libxc/xc_private.h @@ -214,11 +214,12 @@ void xc__hypercall_buffer_cache_release(xc_interface *xch); * Hypercall interfaces. */ -static inline int do_xen_version(xc_interface *xch, int cmd, xc_hypercall_buffer_t *dest) +static inline long do_version_op(xc_interface *xch, int cmd, + xc_hypercall_buffer_t *dest, ssize_t len) { DECLARE_HYPERCALL_BUFFER_ARGUMENT(dest); - return xencall2(xch->xcall, __HYPERVISOR_xen_version, - cmd, HYPERCALL_BUFFER_AS_ARG(dest)); + return xencall3(xch->xcall, __HYPERVISOR_version_op, + cmd, HYPERCALL_BUFFER_AS_ARG(dest), len); } static inline int do_physdev_op(xc_interface *xch, int cmd, void *op, size_t len) diff --git a/tools/libxc/xc_resume.c b/tools/libxc/xc_resume.c index e692b810f7..5bf4cf0f73 100644 --- a/tools/libxc/xc_resume.c +++ b/tools/libxc/xc_resume.c @@ -56,7 +56,8 @@ static int modify_returncode(xc_interface *xch, uint32_t domid) return 0; /* HVM guests have host address width. */ - if ( xc_version(xch, XENVER_capabilities, &caps) != 0 ) + if ( xc_version(xch, XEN_VERSION_capabilities, caps, + sizeof(caps)) < 0 ) { PERROR("Could not get Xen capabilities"); return -1; diff --git a/tools/libxc/xc_sr_save.c b/tools/libxc/xc_sr_save.c index 388ae7fd3a..7f1818caf9 100644 --- a/tools/libxc/xc_sr_save.c +++ b/tools/libxc/xc_sr_save.c @@ -9,7 +9,7 @@ static int write_headers(struct xc_sr_context *ctx, uint16_t guest_type) { xc_interface *xch = ctx->xch; - int32_t xen_version = xc_version(xch, XENVER_version, NULL); + xen_version_op_val_t xen_version; struct xc_sr_ihdr ihdr = { .marker = IHDR_MARKER, @@ -21,15 +21,16 @@ static int write_headers(struct xc_sr_context *ctx, uint16_t guest_type) { .type = guest_type, .page_shift = XC_PAGE_SHIFT, - .xen_major = (xen_version >> 16) & 0xffff, - .xen_minor = (xen_version) & 0xffff, }; - if ( xen_version < 0 ) + if ( xc_version(xch, XEN_VERSION_version, &xen_version, + sizeof(xen_version)) < 0 ) { PERROR("Unable to obtain Xen Version"); return -1; } + dhdr.xen_major = (xen_version >> 16) & 0xffff; + dhdr.xen_minor = (xen_version) & 0xffff; if ( write_exact(ctx->fd, &ihdr, sizeof(ihdr)) ) { diff --git a/tools/libxc/xg_save_restore.h b/tools/libxc/xg_save_restore.h index 303081df0d..007875f6f1 100644 --- a/tools/libxc/xg_save_restore.h +++ b/tools/libxc/xg_save_restore.h @@ -57,10 +57,12 @@ static inline int get_platform_info(xc_interface *xch, uint32_t dom, xen_capabilities_info_t xen_caps = ""; xen_platform_parameters_t xen_params; - if (xc_version(xch, XENVER_platform_parameters, &xen_params) != 0) + if (xc_version(xch, XEN_VERSION_platform_parameters, &xen_params, + sizeof(xen_params)) < 0) return 0; - if (xc_version(xch, XENVER_capabilities, &xen_caps) != 0) + if (xc_version(xch, XEN_VERSION_capabilities, xen_caps, + sizeof(xen_caps)) < 0) return 0; if (xc_maximum_ram_page(xch, max_mfn)) diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index 20e0019d9c..ac4d1f673a 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -5207,50 +5207,71 @@ libxl_numainfo *libxl_get_numainfo(libxl_ctx *ctx, int *nr) return ret; } + +static int libxl__xc_version_wrapper(libxl__gc *gc, unsigned int cmd, + char *buf, ssize_t len, char **dst) +{ + int r; + + r = xc_version(CTX->xch, cmd, buf, len); + if ( r == -EPERM ) { + buf[0] = '\0'; + } else if ( r < 0 ) { + return r; + } + *dst = libxl__strdup(NOGC, buf); + return 0; +} + const libxl_version_info* libxl_get_version_info(libxl_ctx *ctx) { GC_INIT(ctx); - union { - xen_extraversion_t xen_extra; - xen_compile_info_t xen_cc; - xen_changeset_info_t xen_chgset; - xen_capabilities_info_t xen_caps; - xen_platform_parameters_t p_parms; - xen_commandline_t xen_commandline; - } u; - long xen_version; + char *buf; + xen_version_op_val_t val = 0; libxl_version_info *info = &ctx->version_info; if (info->xen_version_extra != NULL) goto out; - xen_version = xc_version(ctx->xch, XENVER_version, NULL); - info->xen_version_major = xen_version >> 16; - info->xen_version_minor = xen_version & 0xFF; + if (xc_version(CTX->xch, XEN_VERSION_pagesize, &val, sizeof(val)) < 0) + goto out; - xc_version(ctx->xch, XENVER_extraversion, &u.xen_extra); - info->xen_version_extra = libxl__strdup(NOGC, u.xen_extra); + info->pagesize = val; + /* 4K buffer. */ + buf = libxl__zalloc(gc, info->pagesize); - xc_version(ctx->xch, XENVER_compile_info, &u.xen_cc); - info->compiler = libxl__strdup(NOGC, u.xen_cc.compiler); - info->compile_by = libxl__strdup(NOGC, u.xen_cc.compile_by); - info->compile_domain = libxl__strdup(NOGC, u.xen_cc.compile_domain); - info->compile_date = libxl__strdup(NOGC, u.xen_cc.compile_date); + val = 0; + if (xc_version(CTX->xch, XEN_VERSION_version, &val, sizeof(val)) < 0) + goto out; + info->xen_version_major = val >> 16; + info->xen_version_minor = val & 0xFF; - xc_version(ctx->xch, XENVER_capabilities, &u.xen_caps); - info->capabilities = libxl__strdup(NOGC, u.xen_caps); + if (libxl__xc_version_wrapper(gc, XEN_VERSION_extraversion, buf, + info->pagesize, &info->xen_version_extra) < 0) + goto out; - xc_version(ctx->xch, XENVER_changeset, &u.xen_chgset); - info->changeset = libxl__strdup(NOGC, u.xen_chgset); + info->compiler = libxl__strdup(NOGC, ""); + info->compile_by = libxl__strdup(NOGC, ""); + info->compile_domain = libxl__strdup(NOGC, ""); + info->compile_date = libxl__strdup(NOGC, ""); - xc_version(ctx->xch, XENVER_platform_parameters, &u.p_parms); - info->virt_start = u.p_parms.virt_start; + if (libxl__xc_version_wrapper(gc, XEN_VERSION_capabilities, buf, + info->pagesize, &info->capabilities) < 0) + goto out; - info->pagesize = xc_version(ctx->xch, XENVER_pagesize, NULL); + if (libxl__xc_version_wrapper(gc, XEN_VERSION_changeset, buf, + info->pagesize, &info->changeset) < 0) + goto out; - xc_version(ctx->xch, XENVER_commandline, &u.xen_commandline); - info->commandline = libxl__strdup(NOGC, u.xen_commandline); + val = 0; + if (xc_version(CTX->xch, XEN_VERSION_platform_parameters, &val, + sizeof(val)) < 0) + goto out; + info->virt_start = val; + + (void)libxl__xc_version_wrapper(gc, XEN_VERSION_commandline, buf, + info->pagesize, &info->commandline); out: GC_FREE; return info; diff --git a/tools/ocaml/libs/xc/xenctrl_stubs.c b/tools/ocaml/libs/xc/xenctrl_stubs.c index 74928e926c..4ac5dce2c4 100644 --- a/tools/ocaml/libs/xc/xenctrl_stubs.c +++ b/tools/ocaml/libs/xc/xenctrl_stubs.c @@ -853,21 +853,21 @@ CAMLprim value stub_xc_version_version(value xch) CAMLparam1(xch); CAMLlocal1(result); xen_extraversion_t extra; - long packed; + xen_version_op_val_t packed; int retval; caml_enter_blocking_section(); - packed = xc_version(_H(xch), XENVER_version, NULL); + retval = xc_version(_H(xch), XEN_VERSION_version, &packed, sizeof(packed)); caml_leave_blocking_section(); - if (packed < 0) + if (retval < 0) failwith_xc(_H(xch)); caml_enter_blocking_section(); - retval = xc_version(_H(xch), XENVER_extraversion, &extra); + retval = xc_version(_H(xch), XEN_VERSION_extraversion, &extra, sizeof(extra)); caml_leave_blocking_section(); - if (retval) + if (retval < 0) failwith_xc(_H(xch)); result = caml_alloc_tuple(3); @@ -884,37 +884,28 @@ CAMLprim value stub_xc_version_compile_info(value xch) { CAMLparam1(xch); CAMLlocal1(result); - xen_compile_info_t ci; - int retval; - - caml_enter_blocking_section(); - retval = xc_version(_H(xch), XENVER_compile_info, &ci); - caml_leave_blocking_section(); - - if (retval) - failwith_xc(_H(xch)); result = caml_alloc_tuple(4); - Store_field(result, 0, caml_copy_string(ci.compiler)); - Store_field(result, 1, caml_copy_string(ci.compile_by)); - Store_field(result, 2, caml_copy_string(ci.compile_domain)); - Store_field(result, 3, caml_copy_string(ci.compile_date)); + Store_field(result, 0, caml_copy_string("")); + Store_field(result, 1, caml_copy_string("")); + Store_field(result, 2, caml_copy_string("")); + Store_field(result, 3, caml_copy_string("")); CAMLreturn(result); } -static value xc_version_single_string(value xch, int code, void *info) +static value xc_version_single_string(value xch, int code, void *info, ssize_t len) { CAMLparam1(xch); int retval; caml_enter_blocking_section(); - retval = xc_version(_H(xch), code, info); + retval = xc_version(_H(xch), code, info, len); caml_leave_blocking_section(); - if (retval) + if (retval < 0) failwith_xc(_H(xch)); CAMLreturn(caml_copy_string((char *)info)); @@ -925,7 +916,8 @@ CAMLprim value stub_xc_version_changeset(value xch) { xen_changeset_info_t ci; - return xc_version_single_string(xch, XENVER_changeset, &ci); + return xc_version_single_string(xch, XEN_VERSION_changeset, + &ci, sizeof(ci)); } @@ -933,7 +925,8 @@ CAMLprim value stub_xc_version_capabilities(value xch) { xen_capabilities_info_t ci; - return xc_version_single_string(xch, XENVER_capabilities, &ci); + return xc_version_single_string(xch, XEN_VERSION_capabilities, + &ci, sizeof(ci)); } diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c index ff714d79bb..d53870f956 100644 --- a/tools/python/xen/lowlevel/xc/xc.c +++ b/tools/python/xen/lowlevel/xc/xc.c @@ -1204,34 +1204,40 @@ static PyObject *pyxc_xeninfo(XcObject *self) xen_capabilities_info_t xen_caps; xen_platform_parameters_t p_parms; xen_commandline_t xen_commandline; - long xen_version; - long xen_pagesize; + xen_version_op_val_t xen_version; + xen_version_op_val_t xen_pagesize; char str[128]; - xen_version = xc_version(self->xc_handle, XENVER_version, NULL); - - if ( xc_version(self->xc_handle, XENVER_extraversion, &xen_extra) != 0 ) + if ( xc_version(self->xc_handle, XEN_VERSION_version, &xen_version, + sizeof(xen_version)) < 0 ) return pyxc_error_to_exception(self->xc_handle); - if ( xc_version(self->xc_handle, XENVER_compile_info, &xen_cc) != 0 ) + if ( xc_version(self->xc_handle, XEN_VERSION_extraversion, &xen_extra, + sizeof(xen_extra)) < 0 ) return pyxc_error_to_exception(self->xc_handle); - if ( xc_version(self->xc_handle, XENVER_changeset, &xen_chgset) != 0 ) + memset(&xen_cc, 0, sizeof(xen_cc)); + + if ( xc_version(self->xc_handle, XEN_VERSION_changeset, &xen_chgset, + sizeof(xen_chgset)) < 0 ) return pyxc_error_to_exception(self->xc_handle); - if ( xc_version(self->xc_handle, XENVER_capabilities, &xen_caps) != 0 ) + if ( xc_version(self->xc_handle, XEN_VERSION_capabilities, &xen_caps, + sizeof(xen_caps)) < 0 ) return pyxc_error_to_exception(self->xc_handle); - if ( xc_version(self->xc_handle, XENVER_platform_parameters, &p_parms) != 0 ) + if ( xc_version(self->xc_handle, XEN_VERSION_platform_parameters, + &p_parms, sizeof(p_parms)) < 0 ) return pyxc_error_to_exception(self->xc_handle); - if ( xc_version(self->xc_handle, XENVER_commandline, &xen_commandline) != 0 ) + if ( xc_version(self->xc_handle, XEN_VERSION_commandline, + &xen_commandline, sizeof(xen_commandline)) < 0 ) return pyxc_error_to_exception(self->xc_handle); snprintf(str, sizeof(str), "virt_start=0x%"PRI_xen_ulong, p_parms.virt_start); - xen_pagesize = xc_version(self->xc_handle, XENVER_pagesize, NULL); - if (xen_pagesize < 0 ) + if ( xc_version(self->xc_handle, XEN_VERSION_pagesize, &xen_pagesize, + sizeof(xen_pagesize)) < 0 ) return pyxc_error_to_exception(self->xc_handle); return Py_BuildValue("{s:i,s:i,s:s,s:s,s:i,s:s,s:s,s:s,s:s,s:s,s:s,s:s}", diff --git a/tools/xenstat/libxenstat/src/xenstat.c b/tools/xenstat/libxenstat/src/xenstat.c index 3495f3fcd7..efb68b5a63 100644 --- a/tools/xenstat/libxenstat/src/xenstat.c +++ b/tools/xenstat/libxenstat/src/xenstat.c @@ -621,20 +621,18 @@ unsigned long long xenstat_network_tdrop(xenstat_network * network) /* Collect Xen version information */ static int xenstat_collect_xen_version(xenstat_node * node) { - long vnum = 0; + xen_version_op_val_t vnum = 0; xen_extraversion_t version; /* Collect Xen version information if not already collected */ if (node->handle->xen_version[0] == '\0') { /* Get the Xen version number and extraversion string */ - vnum = xc_version(node->handle->xc_handle, - XENVER_version, NULL); - - if (vnum < 0) + if (xc_version(node->handle->xc_handle, + XEN_VERSION_version, &vnum, sizeof(vnum)) < 0) return 0; - if (xc_version(node->handle->xc_handle, XENVER_extraversion, - &version) < 0) + if (xc_version(node->handle->xc_handle, XEN_VERSION_extraversion, + &version, sizeof(version)) < 0) return 0; /* Format the version information as a string and store it */ snprintf(node->handle->xen_version, VERSION_SIZE, "%ld.%ld%s", diff --git a/tools/xentrace/xenctx.c b/tools/xentrace/xenctx.c index e647179e19..cd280fc858 100644 --- a/tools/xentrace/xenctx.c +++ b/tools/xentrace/xenctx.c @@ -1000,7 +1000,8 @@ static void dump_ctx(int vcpu) guest_word_size = (cpuctx.msr_efer & 0x400) ? 8 : guest_protected_mode ? 4 : 2; /* HVM guest context records are always host-sized */ - if (xc_version(xenctx.xc_handle, XENVER_capabilities, &xen_caps) != 0) { + if (xc_version(xenctx.xc_handle, XEN_VERSION_capabilities, + &xen_caps, sizeof(xen_caps)) < 0) { perror("xc_version"); return; }