Files
xen/tools/libxc/xc_kexec.c
T
David Vrabel 19f46b0927 libxc: add API for kexec hypercall
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@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Tested-by: Daniel Kiper <daniel.kiper@oracle.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Don Slutz <dslutz@verizon.com>
Tested-by: Don Slutz <dslutz@verizon.com>
Acked-by: Keir Fraser <keir@xen.org>
2013-11-12 11:47:07 +01:00

141 lines
3.6 KiB
C

/******************************************************************************
* 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;
}