[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |