Files
xen/tools/libs/ctrl/xc_resource.c
T
Teddy Astie 9ccbd902df libxc: Report EINVAL in invalid xc_resource_op use
xc_report_op doesn't update errno when called with 0 operations
(even though it returns -1).

Signed-off-by: Teddy Astie <teddy.astie@vates.tech>
Reviewed-by: Anthony PERARD <anthony.perard@vates.tech>
2026-04-02 08:49:17 +02:00

153 lines
4.4 KiB
C

/*
* xc_resource.c
*
* Generic resource access API
*
* Copyright (C) 2014 Intel Corporation
* Author Dongxiao Xu <dongxiao.xu@intel.com>
*
* This program 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 only. with the special
* exception on linking described in file LICENSE.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*/
#include "xc_private.h"
static int xc_resource_op_one(xc_interface *xch, xc_resource_op_t *op)
{
int rc;
struct xen_platform_op platform_op = {};
DECLARE_NAMED_HYPERCALL_BOUNCE(entries, op->entries,
op->nr_entries * sizeof(*op->entries),
XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
if ( xc_hypercall_bounce_pre(xch, entries) )
return -1;
platform_op.cmd = XENPF_resource_op;
platform_op.u.resource_op.nr_entries = op->nr_entries;
platform_op.u.resource_op.cpu = op->cpu;
set_xen_guest_handle(platform_op.u.resource_op.entries, entries);
rc = do_platform_op(xch, &platform_op);
op->result = rc;
xc_hypercall_bounce_post(xch, entries);
return rc;
}
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 xc_resource_op(xc_interface *xch, uint32_t nr_ops, xc_resource_op_t *ops)
{
if ( nr_ops == 1 )
return xc_resource_op_one(xch, ops);
if ( nr_ops > 1 )
return xc_resource_op_multi(xch, nr_ops, ops);
errno = EINVAL;
return -1;
}
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/