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