Exemplo n.º 1
0
static int xc_resource_op_multi(xc_interface *xch, uint32_t nr_ops, xc_resource_op_t *ops)
{
    int rc, i, entries_size;
    xc_resource_op_t *op;
    multicall_entry_t *call;
    DECLARE_HYPERCALL_BUFFER(multicall_entry_t, call_list);
    xc_hypercall_buffer_array_t *platform_ops, *entries_list = NULL;

    call_list = xc_hypercall_buffer_alloc(xch, call_list,
                                          sizeof(*call_list) * nr_ops);
    if ( !call_list )
        return -1;

    platform_ops = xc_hypercall_buffer_array_create(xch, nr_ops);
    if ( !platform_ops )
    {
        rc = -1;
        goto out;
    }

    entries_list = xc_hypercall_buffer_array_create(xch, nr_ops);
    if ( !entries_list )
    {
        rc = -1;
        goto out;
    }

    for ( i = 0; i < nr_ops; i++ )
    {
        DECLARE_HYPERCALL_BUFFER(xen_platform_op_t, platform_op);
        DECLARE_HYPERCALL_BUFFER(xc_resource_entry_t, entries);

        op = ops + i;

        platform_op = xc_hypercall_buffer_array_alloc(xch, platform_ops, i,
                        platform_op, sizeof(xen_platform_op_t));
        if ( !platform_op )
        {
            rc = -1;
            goto out;
        }

        entries_size = sizeof(xc_resource_entry_t) * op->nr_entries;
        entries = xc_hypercall_buffer_array_alloc(xch, entries_list, i,
                   entries, entries_size);
        if ( !entries)
        {
            rc = -1;
            goto out;
        }
        memcpy(entries, op->entries, entries_size);

        call = call_list + i;
        call->op = __HYPERVISOR_platform_op;
        call->args[0] = HYPERCALL_BUFFER_AS_ARG(platform_op);

        platform_op->interface_version = XENPF_INTERFACE_VERSION;
        platform_op->cmd = XENPF_resource_op;
        platform_op->u.resource_op.cpu = op->cpu;
        platform_op->u.resource_op.nr_entries = op->nr_entries;
        set_xen_guest_handle(platform_op->u.resource_op.entries, entries);
    }

    rc = do_multicall_op(xch, HYPERCALL_BUFFER(call_list), nr_ops);

    for ( i = 0; i < nr_ops; i++ )
    {
        DECLARE_HYPERCALL_BUFFER(xc_resource_entry_t, entries);
        op = ops + i;

        call = call_list + i;
        op->result = call->result;

        entries_size = sizeof(xc_resource_entry_t) * op->nr_entries;
        entries = xc_hypercall_buffer_array_get(xch, entries_list, i,
                   entries, entries_size);
        memcpy(op->entries, entries, entries_size);
    }

out:
    xc_hypercall_buffer_array_destroy(xch, entries_list);
    xc_hypercall_buffer_array_destroy(xch, platform_ops);
    xc_hypercall_buffer_free(xch, call_list);
    return rc;
}
Exemplo n.º 2
0
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;
}