[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH 4/4] kexec/xen: directly load images images into Xen



On Fri, Sep 20, 2013 at 02:16:38PM +0100, David Vrabel wrote:
> From: David Vrabel <david.vrabel@xxxxxxxxxx>
>
> Xen 4.4 has an improvided kexec hypercall ABI that allows images to be
> loaded and executed without any kernel involvement.  Use the API
> provided by libxc to load images when running in a Xen guest.
>
> Support for loading images via the kexec_load syscall in non-upstream
> ("classic") Xen kernels is no longer supported.
>
> Signed-off-by: David Vrabel <david.vrabel@xxxxxxxxxx>

[...]

> diff --git a/kexec/kexec-xen.c b/kexec/kexec-xen.c
> new file mode 100644
> index 0000000..0e47e68
> --- /dev/null
> +++ b/kexec/kexec-xen.c
> @@ -0,0 +1,134 @@
> +#define _GNU_SOURCE
> +#include <stdio.h>
> +#include <string.h>
> +#include <stdlib.h>
> +#include <elf.h>
> +#include "kexec.h"
> +#include "kexec-syscall.h"
> +#include "crashdump.h"
> +
> +#include "config.h"
> +
> +#ifdef HAVE_LIBXENCTRL
> +#include <xenctrl.h>
> +
> +#include "crashdump.h"
> +
> +int xen_kexec_load(struct kexec_info *info)
> +{
> +     uint32_t nr_segments = info->nr_segments;
> +     struct kexec_segment *segments = info->segment;
> +     xc_interface *xch;
> +     xc_hypercall_buffer_array_t *array = NULL;
> +     uint8_t type;
> +     uint8_t arch;
> +     xen_kexec_segment_t *xen_segs;
> +     int s;
> +     int ret = -1;
> +
> +     xch = xc_interface_open(NULL, NULL, 0);
> +     if (!xch)
> +             return -1;
> +
> +     xen_segs = calloc(nr_segments + 1, sizeof(*xen_segs));
> +     if (!xen_segs)
> +             goto out;
> +
> +     array = xc_hypercall_buffer_array_create(xch, nr_segments);
> +     if (array == NULL)
> +             goto out;
> +
> +     for (s = 0; s < nr_segments; s++) {
> +             DECLARE_HYPERCALL_BUFFER(void, seg_buf);
> +
> +             seg_buf = xc_hypercall_buffer_array_alloc(xch, array, s,
> +                                                       seg_buf, 
> segments[s].bufsz);
> +             if (seg_buf == NULL)
> +                     goto out;
> +             memcpy(seg_buf, segments[s].buf, segments[s].bufsz);
> +
> +             set_xen_guest_handle(xen_segs[s].buf.h, seg_buf);
> +             xen_segs[s].buf_size = segments[s].bufsz;
> +             xen_segs[s].dest_maddr = (uint64_t)segments[s].mem;
> +             xen_segs[s].dest_size = segments[s].memsz;
> +     }
> +
> +     if (info->kexec_flags & KEXEC_ON_CRASH) {
> +             set_xen_guest_handle(xen_segs[s].buf.h, HYPERCALL_BUFFER_NULL);
> +             xen_segs[s].buf_size = 0;
> +             xen_segs[s].dest_maddr = info->backup_src_start;
> +             xen_segs[s].dest_size = info->backup_src_size;
> +             nr_segments++;
> +     }
> +
> +     type = (info->kexec_flags & KEXEC_ON_CRASH) ? KEXEC_TYPE_CRASH
> +             : KEXEC_TYPE_DEFAULT;
> +
> +     arch = (info->kexec_flags & KEXEC_ARCH_MASK) >> 16;
> +#if defined(_i386__) || defined(__x86_64__)
> +     if (!arch)
> +             arch = EM_386;
> +#endif
> +
> +     ret = xc_kexec_load(xch, type, arch, (uint64_t)info->entry,
> +                         nr_segments, xen_segs);
> +
> +out:
> +     xc_hypercall_buffer_array_destroy(xch, array);
> +     free(xen_segs);
> +     xc_interface_close(xch);
> +
> +     return ret;
> +}
> +
> +int xen_kexec_unload(uint64_t kexec_flags)
> +{
> +     xc_interface *xch;
> +     uint8_t type;
> +     int ret;
> +
> +     xch = xc_interface_open(NULL, NULL, 0);
> +     if (!xch)
> +             return -1;
> +
> +     type = kexec_flags & KEXEC_TYPE_CRASH;

Why? Could not we unload normal kexec images?

> +     ret = xc_kexec_unload(xch, type);
> +
> +     xc_interface_close(xch);
> +
> +     return ret;
> +}
> +
> +void xen_kexec_exec(void)
> +{
> +     xc_interface *xch;
> +
> +     xch = xc_interface_open(NULL, NULL, 0);
> +     if (!xch)
> +             return;
> +
> +     xc_kexec_exec(xch, KEXEC_TYPE_DEFAULT);
> +
> +     xc_interface_close(xch);
> +}
> +
> +#else /* ! HAVE_LIBXENCTRL */
> +
> +int xen_kexec_load(uint64_t entry,
> +                uint32_t nr_segments, struct kexec_segment *segments,
> +                uint64_t kexec_flags)
> +{
> +     return -1;
> +}
> +
> +int xen_kexec_unload(uin64_t kexec_flags);
> +{
> +     return -1;
> +}
> +
> +void xen_kexec_exec(void)
> +{
> +}
> +
> +#endif
> diff --git a/kexec/kexec.c b/kexec/kexec.c
> index 21ff0e7..13b568f 100644
> --- a/kexec/kexec.c
> +++ b/kexec/kexec.c
> @@ -764,8 +764,12 @@ static int my_load(const char *type, int fileind, int 
> argc, char **argv,
>       if (kexec_debug)
>               print_segments(stderr, &info);
>
> -     result = kexec_load(
> -             info.entry, info.nr_segments, info.segment, info.kexec_flags);
> +     if (xen_present())
> +             result = xen_kexec_load(&info);
> +     else
> +             result = kexec_load(info.entry,
> +                                 info.nr_segments, info.segment,
> +                                 info.kexec_flags);
>       if (result != 0) {
>               /* The load failed, print some debugging information */
>               fprintf(stderr, "kexec_load failed: %s\n",
> @@ -789,10 +793,13 @@ static int k_unload (unsigned long kexec_flags)
>       }
>       kexec_flags |= native_arch;
>
> -     result = kexec_load(NULL, 0, NULL, kexec_flags);
> +     if (xen_present())
> +             result = xen_kexec_unload(kexec_flags);
> +     else
> +             result = kexec_load(NULL, 0, NULL, kexec_flags);
>       if (result != 0) {
>               /* The unload failed, print some debugging information */
> -             fprintf(stderr, "kexec_load (0 segments) failed: %s\n",
> +             fprintf(stderr, "kexec unload failed: %s\n",
>                       strerror(errno));
>       }
>       return result;
> @@ -823,7 +830,10 @@ static int my_shutdown(void)
>   */
>  static int my_exec(void)
>  {
> -     reboot(LINUX_REBOOT_CMD_KEXEC);
> +     if (xen_present())
> +             xen_kexec_exec();
> +     else
> +             reboot(LINUX_REBOOT_CMD_KEXEC);
>       /* I have failed if I make it here */
>       fprintf(stderr, "kexec failed: %s\n",
>               strerror(errno));
> @@ -928,6 +938,10 @@ static int kexec_loaded(void)
>       char *p;
>       char line[3];
>
> +     /* No way to tell if an image is loaded under Xen, assume it is. */
> +     if (xen_present())
> +             return 1;
> +

Why? I think that we should have relevant machanism to do that.

Please take into account Konrad's comments too
(http://lists.xenproject.org/archives/html/xen-devel/2013-09/msg02364.html).

Daniel

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.