[PATCH 7/9] libxc: add API for kexec hypercall

Don Slutz dslutz at verizon.com
Thu Nov 7 15:48:06 EST 2013


For what it is worth.

Reviewed-by: Don Slutz <dslutz at verizon.com>
     -Don Slutz

On 11/06/13 09:49, David Vrabel wrote:
> From: David Vrabel <david.vrabel at citrix.com>
>
> Add xc_kexec_exec(), xc_kexec_get_ranges(), xc_kexec_load(), and
> xc_kexec_unload().  The load and unload calls require the v2 load and
> unload ops.
>
> Signed-off-by: David Vrabel <david.vrabel at citrix.com>
> Acked-by: Ian Campbell <ian.campbell at citrix.com>
> Reviewed-by: Daniel Kiper <daniel.kiper at oracle.com>
> Tested-by: Daniel Kiper <daniel.kiper at oracle.com>
> Reviewed-by: Andrew Cooper <andrew.cooper3 at citrix.com>
> ---
>   tools/libxc/Makefile   |    1 +
>   tools/libxc/xc_kexec.c |  140 ++++++++++++++++++++++++++++++++++++++++++++++++
>   tools/libxc/xenctrl.h  |   55 +++++++++++++++++++
>   3 files changed, 196 insertions(+), 0 deletions(-)
>   create mode 100644 tools/libxc/xc_kexec.c
>
> diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
> index 4c64c15..f2d6e56 100644
> --- a/tools/libxc/Makefile
> +++ b/tools/libxc/Makefile
> @@ -31,6 +31,7 @@ CTRL_SRCS-y       += xc_mem_access.c
>   CTRL_SRCS-y       += xc_memshr.c
>   CTRL_SRCS-y       += xc_hcall_buf.c
>   CTRL_SRCS-y       += xc_foreign_memory.c
> +CTRL_SRCS-y       += xc_kexec.c
>   CTRL_SRCS-y       += xtl_core.c
>   CTRL_SRCS-y       += xtl_logger_stdio.c
>   CTRL_SRCS-$(CONFIG_X86) += xc_pagetab.c
> diff --git a/tools/libxc/xc_kexec.c b/tools/libxc/xc_kexec.c
> new file mode 100644
> index 0000000..a49cffb
> --- /dev/null
> +++ b/tools/libxc/xc_kexec.c
> @@ -0,0 +1,140 @@
> +/******************************************************************************
> + * xc_kexec.c
> + *
> + * API for loading and executing kexec images.
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation;
> + * version 2.1 of the License.
> + *
> + * Copyright (C) 2013 Citrix Systems R&D Ltd.
> + */
> +#include "xc_private.h"
> +
> +int xc_kexec_exec(xc_interface *xch, int type)
> +{
> +    DECLARE_HYPERCALL;
> +    DECLARE_HYPERCALL_BUFFER(xen_kexec_exec_t, exec);
> +    int ret = -1;
> +
> +    exec = xc_hypercall_buffer_alloc(xch, exec, sizeof(*exec));
> +    if ( exec == NULL )
> +    {
> +        PERROR("Count not alloc bounce buffer for kexec_exec hypercall");
> +        goto out;
> +    }
> +
> +    exec->type = type;
> +
> +    hypercall.op = __HYPERVISOR_kexec_op;
> +    hypercall.arg[0] = KEXEC_CMD_kexec;
> +    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(exec);
> +
> +    ret = do_xen_hypercall(xch, &hypercall);
> +
> +out:
> +    xc_hypercall_buffer_free(xch, exec);
> +
> +    return ret;
> +}
> +
> +int xc_kexec_get_range(xc_interface *xch, int range,  int nr,
> +                       uint64_t *size, uint64_t *start)
> +{
> +    DECLARE_HYPERCALL;
> +    DECLARE_HYPERCALL_BUFFER(xen_kexec_range_t, get_range);
> +    int ret = -1;
> +
> +    get_range = xc_hypercall_buffer_alloc(xch, get_range, sizeof(*get_range));
> +    if ( get_range == NULL )
> +    {
> +        PERROR("Could not alloc bounce buffer for kexec_get_range hypercall");
> +        goto out;
> +    }
> +
> +    get_range->range = range;
> +    get_range->nr = nr;
> +
> +    hypercall.op = __HYPERVISOR_kexec_op;
> +    hypercall.arg[0] = KEXEC_CMD_kexec_get_range;
> +    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(get_range);
> +
> +    ret = do_xen_hypercall(xch, &hypercall);
> +
> +    *size = get_range->size;
> +    *start = get_range->start;
> +
> +out:
> +    xc_hypercall_buffer_free(xch, get_range);
> +
> +    return ret;
> +}
> +
> +int xc_kexec_load(xc_interface *xch, uint8_t type, uint16_t arch,
> +                  uint64_t entry_maddr,
> +                  uint32_t nr_segments, xen_kexec_segment_t *segments)
> +{
> +    int ret = -1;
> +    DECLARE_HYPERCALL;
> +    DECLARE_HYPERCALL_BOUNCE(segments, sizeof(*segments) * nr_segments,
> +                             XC_HYPERCALL_BUFFER_BOUNCE_IN);
> +    DECLARE_HYPERCALL_BUFFER(xen_kexec_load_t, load);
> +
> +    if ( xc_hypercall_bounce_pre(xch, segments) )
> +    {
> +        PERROR("Could not allocate bounce buffer for kexec load hypercall");
> +        goto out;
> +    }
> +    load = xc_hypercall_buffer_alloc(xch, load, sizeof(*load));
> +    if ( load == NULL )
> +    {
> +        PERROR("Could not allocate buffer for kexec load hypercall");
> +        goto out;
> +    }
> +
> +    load->type = type;
> +    load->arch = arch;
> +    load->entry_maddr = entry_maddr;
> +    load->nr_segments = nr_segments;
> +    set_xen_guest_handle(load->segments.h, segments);
> +
> +    hypercall.op = __HYPERVISOR_kexec_op;
> +    hypercall.arg[0] = KEXEC_CMD_kexec_load;
> +    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(load);
> +
> +    ret = do_xen_hypercall(xch, &hypercall);
> +
> +out:
> +    xc_hypercall_buffer_free(xch, load);
> +    xc_hypercall_bounce_post(xch, segments);
> +
> +    return ret;
> +}
> +
> +int xc_kexec_unload(xc_interface *xch, int type)
> +{
> +    DECLARE_HYPERCALL;
> +    DECLARE_HYPERCALL_BUFFER(xen_kexec_unload_t, unload);
> +    int ret = -1;
> +
> +    unload = xc_hypercall_buffer_alloc(xch, unload, sizeof(*unload));
> +    if ( unload == NULL )
> +    {
> +        PERROR("Count not alloc buffer for kexec unload hypercall");
> +        goto out;
> +    }
> +
> +    unload->type = type;
> +
> +    hypercall.op = __HYPERVISOR_kexec_op;
> +    hypercall.arg[0] = KEXEC_CMD_kexec_unload;
> +    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(unload);
> +
> +    ret = do_xen_hypercall(xch, &hypercall);
> +
> +out:
> +    xc_hypercall_buffer_free(xch, unload);
> +
> +    return ret;
> +}
> diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
> index a7e8c31..4ac6b8a 100644
> --- a/tools/libxc/xenctrl.h
> +++ b/tools/libxc/xenctrl.h
> @@ -46,6 +46,7 @@
>   #include <xen/hvm/params.h>
>   #include <xen/xsm/flask_op.h>
>   #include <xen/tmem.h>
> +#include <xen/kexec.h>
>   
>   #include "xentoollog.h"
>   
> @@ -2340,4 +2341,58 @@ int xc_compression_uncompress_page(xc_interface *xch, char *compbuf,
>   				   unsigned long compbuf_size,
>   				   unsigned long *compbuf_pos, char *dest);
>   
> +/*
> + * Execute an image previously loaded with xc_kexec_load().
> + *
> + * Does not return on success.
> + *
> + * Fails with:
> + *   ENOENT if the specified image has not been loaded.
> + */
> +int xc_kexec_exec(xc_interface *xch, int type);
> +
> +/*
> + * Find the machine address and size of certain memory areas.
> + *
> + *   KEXEC_RANGE_MA_CRASH       crash area
> + *   KEXEC_RANGE_MA_XEN         Xen itself
> + *   KEXEC_RANGE_MA_CPU         CPU note for CPU number 'nr'
> + *   KEXEC_RANGE_MA_XENHEAP     xenheap
> + *   KEXEC_RANGE_MA_EFI_MEMMAP  EFI Memory Map
> + *   KEXEC_RANGE_MA_VMCOREINFO  vmcoreinfo
> + *
> + * Fails with:
> + *   EINVAL if the range or CPU number isn't valid.
> + */
> +int xc_kexec_get_range(xc_interface *xch, int range,  int nr,
> +                       uint64_t *size, uint64_t *start);
> +
> +/*
> + * Load a kexec image into memory.
> + *
> + * The image may be of type KEXEC_TYPE_DEFAULT (executed on request)
> + * or KEXEC_TYPE_CRASH (executed on a crash).
> + *
> + * The image architecture may be a 32-bit variant of the hypervisor
> + * architecture (e.g, EM_386 on a x86-64 hypervisor).
> + *
> + * Fails with:
> + *   ENOMEM if there is insufficient memory for the new image.
> + *   EINVAL if the image does not fit into the crash area or the entry
> + *          point isn't within one of segments.
> + *   EBUSY  if another image is being executed.
> + */
> +int xc_kexec_load(xc_interface *xch, uint8_t type, uint16_t arch,
> +                  uint64_t entry_maddr,
> +                  uint32_t nr_segments, xen_kexec_segment_t *segments);
> +
> +/*
> + * Unload a kexec image.
> + *
> + * This prevents a KEXEC_TYPE_DEFAULT or KEXEC_TYPE_CRASH image from
> + * being executed.  The crash images are not cleared from the crash
> + * region.
> + */
> +int xc_kexec_unload(xc_interface *xch, int type);
> +
>   #endif /* XENCTRL_H */




More information about the kexec mailing list