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

Simon Horman horms at verge.net.au
Mon Nov 18 20:20:14 EST 2013


On Wed, Nov 06, 2013 at 02:55:22PM +0000, David Vrabel wrote:
> From: David Vrabel <david.vrabel at citrix.com>
> 
> 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 at citrix.com>
> Reviewed-by: Daniel Kiper <daniel.kiper at oracle.com>
> ---
>  kexec/Makefile                  |    1 +
>  kexec/arch/i386/crashdump-x86.c |   20 +++++-
>  kexec/crashdump-xen.c           |   34 ++++++++++
>  kexec/crashdump.h               |    3 +-
>  kexec/kexec-xen.c               |  139 +++++++++++++++++++++++++++++++++++++++
>  kexec/kexec.c                   |   24 +++++--
>  kexec/kexec.h                   |    5 ++
>  7 files changed, 218 insertions(+), 8 deletions(-)
>  create mode 100644 kexec/kexec-xen.c
> 

[snip]

> diff --git a/kexec/kexec-xen.c b/kexec/kexec-xen.c
> new file mode 100644
> index 0000000..77f65c0
> --- /dev/null
> +++ b/kexec/kexec-xen.c
> @@ -0,0 +1,139 @@
> +#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;
> +	}
> +
> +	/*
> +	 * Ensure 0 - 1 MiB is mapped and accessible by the image.
> +	 *
> +	 * This allows access to the VGA memory and the region
> +	 * purgatory copies in the crash case.
> +	 */
> +	set_xen_guest_handle(xen_segs[s].buf.h, HYPERCALL_BUFFER_NULL);
> +	xen_segs[s].buf_size = 0;
> +	xen_segs[s].dest_maddr = 0;
> +	xen_segs[s].dest_size = 1 * 1024 * 1024;
> +	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_ON_CRASH) ? KEXEC_TYPE_CRASH
> +		: KEXEC_TYPE_DEFAULT;
> +
> +	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

[snip]

I have applied the following follow-up patch to resolves some errors.
Let me know if I messed it up.

From: Simon Horman <horms at verge.net.au>

[PATCH] kexec/xen: Correct some compile errors

Correct various problems introduced by
08cf823704b0fa3b ("kexec/xen: directly load images images into Xen").

These all relate to the case here HAVE_LIBXENCTRL is not set.

Signed-off-by: Simon Horman <horms at verge.net.au>
---
 kexec/kexec-xen.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/kexec/kexec-xen.c b/kexec/kexec-xen.c
index 77f65c0..e885246 100644
--- a/kexec/kexec-xen.c
+++ b/kexec/kexec-xen.c
@@ -2,6 +2,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
+#include <stdlib.h>
 #include <elf.h>
 #include "kexec.h"
 #include "kexec-syscall.h"
@@ -120,14 +121,12 @@ void xen_kexec_exec(void)
 
 #else /* ! HAVE_LIBXENCTRL */
 
-int xen_kexec_load(uint64_t entry,
-		   uint32_t nr_segments, struct kexec_segment *segments,
-		   uint64_t kexec_flags)
+int xen_kexec_load(struct kexec_info *UNUSED(info))
 {
 	return -1;
 }
 
-int xen_kexec_unload(uin64_t kexec_flags);
+int xen_kexec_unload(uint64_t kexec_flags)
 {
 	return -1;
 }
-- 
1.8.4




More information about the kexec mailing list