mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
backing off to the old behaviour if we fail. Signed-off-by: Tim Deegan <Tim.Deegan@citrix.com>
949 lines
25 KiB
C
949 lines
25 KiB
C
/******************************************************************************
|
|
* xc_domain.c
|
|
*
|
|
* API for manipulating and obtaining information on domains.
|
|
*
|
|
* Copyright (c) 2003, K A Fraser.
|
|
*/
|
|
|
|
#include "xc_private.h"
|
|
#include "xg_save_restore.h"
|
|
#include <xen/memory.h>
|
|
#include <xen/hvm/hvm_op.h>
|
|
|
|
int xc_domain_create(int xc_handle,
|
|
uint32_t ssidref,
|
|
xen_domain_handle_t handle,
|
|
uint32_t flags,
|
|
uint32_t *pdomid)
|
|
{
|
|
int err;
|
|
DECLARE_DOMCTL;
|
|
|
|
domctl.cmd = XEN_DOMCTL_createdomain;
|
|
domctl.domain = (domid_t)*pdomid;
|
|
domctl.u.createdomain.ssidref = ssidref;
|
|
domctl.u.createdomain.flags = flags;
|
|
memcpy(domctl.u.createdomain.handle, handle, sizeof(xen_domain_handle_t));
|
|
if ( (err = do_domctl(xc_handle, &domctl)) != 0 )
|
|
return err;
|
|
|
|
*pdomid = (uint16_t)domctl.domain;
|
|
return 0;
|
|
}
|
|
|
|
|
|
int xc_domain_pause(int xc_handle,
|
|
uint32_t domid)
|
|
{
|
|
DECLARE_DOMCTL;
|
|
domctl.cmd = XEN_DOMCTL_pausedomain;
|
|
domctl.domain = (domid_t)domid;
|
|
return do_domctl(xc_handle, &domctl);
|
|
}
|
|
|
|
|
|
int xc_domain_unpause(int xc_handle,
|
|
uint32_t domid)
|
|
{
|
|
DECLARE_DOMCTL;
|
|
domctl.cmd = XEN_DOMCTL_unpausedomain;
|
|
domctl.domain = (domid_t)domid;
|
|
return do_domctl(xc_handle, &domctl);
|
|
}
|
|
|
|
|
|
int xc_domain_destroy(int xc_handle,
|
|
uint32_t domid)
|
|
{
|
|
int ret;
|
|
DECLARE_DOMCTL;
|
|
domctl.cmd = XEN_DOMCTL_destroydomain;
|
|
domctl.domain = (domid_t)domid;
|
|
do {
|
|
ret = do_domctl(xc_handle, &domctl);
|
|
} while ( ret && (errno == EAGAIN) );
|
|
return ret;
|
|
}
|
|
|
|
int xc_domain_shutdown(int xc_handle,
|
|
uint32_t domid,
|
|
int reason)
|
|
{
|
|
int ret = -1;
|
|
sched_remote_shutdown_t arg;
|
|
DECLARE_HYPERCALL;
|
|
|
|
hypercall.op = __HYPERVISOR_sched_op;
|
|
hypercall.arg[0] = (unsigned long)SCHEDOP_remote_shutdown;
|
|
hypercall.arg[1] = (unsigned long)&arg;
|
|
arg.domain_id = domid;
|
|
arg.reason = reason;
|
|
|
|
if ( lock_pages(&arg, sizeof(arg)) != 0 )
|
|
{
|
|
PERROR("Could not lock memory for Xen hypercall");
|
|
goto out1;
|
|
}
|
|
|
|
ret = do_xen_hypercall(xc_handle, &hypercall);
|
|
|
|
unlock_pages(&arg, sizeof(arg));
|
|
|
|
out1:
|
|
return ret;
|
|
}
|
|
|
|
|
|
int xc_vcpu_setaffinity(int xc_handle,
|
|
uint32_t domid,
|
|
int vcpu,
|
|
uint64_t cpumap)
|
|
{
|
|
DECLARE_DOMCTL;
|
|
int ret = -1;
|
|
uint8_t local[sizeof (cpumap)];
|
|
|
|
domctl.cmd = XEN_DOMCTL_setvcpuaffinity;
|
|
domctl.domain = (domid_t)domid;
|
|
domctl.u.vcpuaffinity.vcpu = vcpu;
|
|
|
|
bitmap_64_to_byte(local, &cpumap, sizeof(cpumap) * 8);
|
|
|
|
set_xen_guest_handle(domctl.u.vcpuaffinity.cpumap.bitmap, local);
|
|
|
|
domctl.u.vcpuaffinity.cpumap.nr_cpus = sizeof(cpumap) * 8;
|
|
|
|
if ( lock_pages(local, sizeof(local)) != 0 )
|
|
{
|
|
PERROR("Could not lock memory for Xen hypercall");
|
|
goto out;
|
|
}
|
|
|
|
ret = do_domctl(xc_handle, &domctl);
|
|
|
|
unlock_pages(local, sizeof(local));
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
|
|
int xc_vcpu_getaffinity(int xc_handle,
|
|
uint32_t domid,
|
|
int vcpu,
|
|
uint64_t *cpumap)
|
|
{
|
|
DECLARE_DOMCTL;
|
|
int ret = -1;
|
|
uint8_t local[sizeof (cpumap)];
|
|
|
|
domctl.cmd = XEN_DOMCTL_getvcpuaffinity;
|
|
domctl.domain = (domid_t)domid;
|
|
domctl.u.vcpuaffinity.vcpu = vcpu;
|
|
|
|
set_xen_guest_handle(domctl.u.vcpuaffinity.cpumap.bitmap, local);
|
|
domctl.u.vcpuaffinity.cpumap.nr_cpus = sizeof(cpumap) * 8;
|
|
|
|
if ( lock_pages(local, sizeof(local)) != 0 )
|
|
{
|
|
PERROR("Could not lock memory for Xen hypercall");
|
|
goto out;
|
|
}
|
|
|
|
ret = do_domctl(xc_handle, &domctl);
|
|
|
|
unlock_pages(local, sizeof (local));
|
|
bitmap_byte_to_64(cpumap, local, sizeof(local) * 8);
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
|
|
int xc_domain_getinfo(int xc_handle,
|
|
uint32_t first_domid,
|
|
unsigned int max_doms,
|
|
xc_dominfo_t *info)
|
|
{
|
|
unsigned int nr_doms;
|
|
uint32_t next_domid = first_domid;
|
|
DECLARE_DOMCTL;
|
|
int rc = 0;
|
|
|
|
memset(info, 0, max_doms*sizeof(xc_dominfo_t));
|
|
|
|
for ( nr_doms = 0; nr_doms < max_doms; nr_doms++ )
|
|
{
|
|
domctl.cmd = XEN_DOMCTL_getdomaininfo;
|
|
domctl.domain = (domid_t)next_domid;
|
|
if ( (rc = do_domctl(xc_handle, &domctl)) < 0 )
|
|
break;
|
|
info->domid = (uint16_t)domctl.domain;
|
|
|
|
info->dying = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_dying);
|
|
info->shutdown = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_shutdown);
|
|
info->paused = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_paused);
|
|
info->blocked = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_blocked);
|
|
info->running = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_running);
|
|
info->hvm = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_hvm_guest);
|
|
info->debugged = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_debugged);
|
|
|
|
info->shutdown_reason =
|
|
(domctl.u.getdomaininfo.flags>>XEN_DOMINF_shutdownshift) &
|
|
XEN_DOMINF_shutdownmask;
|
|
|
|
if ( info->shutdown && (info->shutdown_reason == SHUTDOWN_crash) )
|
|
{
|
|
info->shutdown = 0;
|
|
info->crashed = 1;
|
|
}
|
|
|
|
info->ssidref = domctl.u.getdomaininfo.ssidref;
|
|
info->nr_pages = domctl.u.getdomaininfo.tot_pages;
|
|
info->max_memkb = domctl.u.getdomaininfo.max_pages << (PAGE_SHIFT-10);
|
|
info->shared_info_frame = domctl.u.getdomaininfo.shared_info_frame;
|
|
info->cpu_time = domctl.u.getdomaininfo.cpu_time;
|
|
info->nr_online_vcpus = domctl.u.getdomaininfo.nr_online_vcpus;
|
|
info->max_vcpu_id = domctl.u.getdomaininfo.max_vcpu_id;
|
|
|
|
memcpy(info->handle, domctl.u.getdomaininfo.handle,
|
|
sizeof(xen_domain_handle_t));
|
|
|
|
next_domid = (uint16_t)domctl.domain + 1;
|
|
info++;
|
|
}
|
|
|
|
if ( nr_doms == 0 )
|
|
return rc;
|
|
|
|
return nr_doms;
|
|
}
|
|
|
|
int xc_domain_getinfolist(int xc_handle,
|
|
uint32_t first_domain,
|
|
unsigned int max_domains,
|
|
xc_domaininfo_t *info)
|
|
{
|
|
int ret = 0;
|
|
DECLARE_SYSCTL;
|
|
|
|
if ( lock_pages(info, max_domains*sizeof(xc_domaininfo_t)) != 0 )
|
|
return -1;
|
|
|
|
sysctl.cmd = XEN_SYSCTL_getdomaininfolist;
|
|
sysctl.u.getdomaininfolist.first_domain = first_domain;
|
|
sysctl.u.getdomaininfolist.max_domains = max_domains;
|
|
set_xen_guest_handle(sysctl.u.getdomaininfolist.buffer, info);
|
|
|
|
if ( xc_sysctl(xc_handle, &sysctl) < 0 )
|
|
ret = -1;
|
|
else
|
|
ret = sysctl.u.getdomaininfolist.num_domains;
|
|
|
|
unlock_pages(info, max_domains*sizeof(xc_domaininfo_t));
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* get info from hvm guest for save */
|
|
int xc_domain_hvm_getcontext(int xc_handle,
|
|
uint32_t domid,
|
|
uint8_t *ctxt_buf,
|
|
uint32_t size)
|
|
{
|
|
int ret;
|
|
DECLARE_DOMCTL;
|
|
|
|
domctl.cmd = XEN_DOMCTL_gethvmcontext;
|
|
domctl.domain = (domid_t)domid;
|
|
domctl.u.hvmcontext.size = size;
|
|
set_xen_guest_handle(domctl.u.hvmcontext.buffer, ctxt_buf);
|
|
|
|
if ( ctxt_buf )
|
|
if ( (ret = lock_pages(ctxt_buf, size)) != 0 )
|
|
return ret;
|
|
|
|
ret = do_domctl(xc_handle, &domctl);
|
|
|
|
if ( ctxt_buf )
|
|
unlock_pages(ctxt_buf, size);
|
|
|
|
return (ret < 0 ? -1 : domctl.u.hvmcontext.size);
|
|
}
|
|
|
|
/* set info to hvm guest for restore */
|
|
int xc_domain_hvm_setcontext(int xc_handle,
|
|
uint32_t domid,
|
|
uint8_t *ctxt_buf,
|
|
uint32_t size)
|
|
{
|
|
int ret;
|
|
DECLARE_DOMCTL;
|
|
|
|
domctl.cmd = XEN_DOMCTL_sethvmcontext;
|
|
domctl.domain = domid;
|
|
domctl.u.hvmcontext.size = size;
|
|
set_xen_guest_handle(domctl.u.hvmcontext.buffer, ctxt_buf);
|
|
|
|
if ( (ret = lock_pages(ctxt_buf, size)) != 0 )
|
|
return ret;
|
|
|
|
ret = do_domctl(xc_handle, &domctl);
|
|
|
|
unlock_pages(ctxt_buf, size);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int xc_vcpu_getcontext(int xc_handle,
|
|
uint32_t domid,
|
|
uint32_t vcpu,
|
|
vcpu_guest_context_t *ctxt)
|
|
{
|
|
int rc;
|
|
DECLARE_DOMCTL;
|
|
size_t sz = sizeof(vcpu_guest_context_either_t);
|
|
|
|
domctl.cmd = XEN_DOMCTL_getvcpucontext;
|
|
domctl.domain = (domid_t)domid;
|
|
domctl.u.vcpucontext.vcpu = (uint16_t)vcpu;
|
|
set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt);
|
|
|
|
/*
|
|
* We may be asked to lock either a 32-bit or a 64-bit context. Lock the
|
|
* larger of the two if possible, otherwise fall back to native size.
|
|
*/
|
|
if ( (rc = lock_pages(ctxt, sz)) != 0 )
|
|
{
|
|
sz = sizeof(*ctxt);
|
|
if ( (rc = lock_pages(ctxt, sz)) != 0 )
|
|
return rc;
|
|
}
|
|
|
|
rc = do_domctl(xc_handle, &domctl);
|
|
|
|
unlock_pages(ctxt, sz);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
int xc_shadow_control(int xc_handle,
|
|
uint32_t domid,
|
|
unsigned int sop,
|
|
unsigned long *dirty_bitmap,
|
|
unsigned long pages,
|
|
unsigned long *mb,
|
|
uint32_t mode,
|
|
xc_shadow_op_stats_t *stats)
|
|
{
|
|
int rc;
|
|
DECLARE_DOMCTL;
|
|
domctl.cmd = XEN_DOMCTL_shadow_op;
|
|
domctl.domain = (domid_t)domid;
|
|
domctl.u.shadow_op.op = sop;
|
|
domctl.u.shadow_op.pages = pages;
|
|
domctl.u.shadow_op.mb = mb ? *mb : 0;
|
|
domctl.u.shadow_op.mode = mode;
|
|
set_xen_guest_handle(domctl.u.shadow_op.dirty_bitmap,
|
|
(uint8_t *)dirty_bitmap);
|
|
|
|
rc = do_domctl(xc_handle, &domctl);
|
|
|
|
if ( stats )
|
|
memcpy(stats, &domctl.u.shadow_op.stats,
|
|
sizeof(xc_shadow_op_stats_t));
|
|
|
|
if ( mb )
|
|
*mb = domctl.u.shadow_op.mb;
|
|
|
|
return (rc == 0) ? domctl.u.shadow_op.pages : rc;
|
|
}
|
|
|
|
int xc_domain_setmaxmem(int xc_handle,
|
|
uint32_t domid,
|
|
unsigned int max_memkb)
|
|
{
|
|
DECLARE_DOMCTL;
|
|
domctl.cmd = XEN_DOMCTL_max_mem;
|
|
domctl.domain = (domid_t)domid;
|
|
domctl.u.max_mem.max_memkb = max_memkb;
|
|
return do_domctl(xc_handle, &domctl);
|
|
}
|
|
|
|
int xc_domain_pin_memory_cacheattr(int xc_handle,
|
|
uint32_t domid,
|
|
uint64_t start,
|
|
uint64_t end,
|
|
uint32_t type)
|
|
{
|
|
DECLARE_DOMCTL;
|
|
domctl.cmd = XEN_DOMCTL_pin_mem_cacheattr;
|
|
domctl.domain = (domid_t)domid;
|
|
domctl.u.pin_mem_cacheattr.start = start;
|
|
domctl.u.pin_mem_cacheattr.end = end;
|
|
domctl.u.pin_mem_cacheattr.type = type;
|
|
return do_domctl(xc_handle, &domctl);
|
|
}
|
|
|
|
#if defined(__i386__) || defined(__x86_64__)
|
|
#include "xc_e820.h"
|
|
int xc_domain_set_memmap_limit(int xc_handle,
|
|
uint32_t domid,
|
|
unsigned long map_limitkb)
|
|
{
|
|
int rc;
|
|
|
|
struct xen_foreign_memory_map fmap = {
|
|
.domid = domid,
|
|
.map = { .nr_entries = 1 }
|
|
};
|
|
|
|
struct e820entry e820 = {
|
|
.addr = 0,
|
|
.size = (uint64_t)map_limitkb << 10,
|
|
.type = E820_RAM
|
|
};
|
|
|
|
set_xen_guest_handle(fmap.map.buffer, &e820);
|
|
|
|
if ( lock_pages(&fmap, sizeof(fmap)) || lock_pages(&e820, sizeof(e820)) )
|
|
{
|
|
PERROR("Could not lock memory for Xen hypercall");
|
|
rc = -1;
|
|
goto out;
|
|
}
|
|
|
|
rc = xc_memory_op(xc_handle, XENMEM_set_memory_map, &fmap);
|
|
|
|
out:
|
|
unlock_pages(&fmap, sizeof(fmap));
|
|
unlock_pages(&e820, sizeof(e820));
|
|
return rc;
|
|
}
|
|
#else
|
|
int xc_domain_set_memmap_limit(int xc_handle,
|
|
uint32_t domid,
|
|
unsigned long map_limitkb)
|
|
{
|
|
PERROR("Function not implemented");
|
|
errno = ENOSYS;
|
|
return -1;
|
|
}
|
|
#endif
|
|
|
|
int xc_domain_set_time_offset(int xc_handle,
|
|
uint32_t domid,
|
|
int32_t time_offset_seconds)
|
|
{
|
|
DECLARE_DOMCTL;
|
|
domctl.cmd = XEN_DOMCTL_settimeoffset;
|
|
domctl.domain = (domid_t)domid;
|
|
domctl.u.settimeoffset.time_offset_seconds = time_offset_seconds;
|
|
return do_domctl(xc_handle, &domctl);
|
|
}
|
|
|
|
int xc_domain_memory_increase_reservation(int xc_handle,
|
|
uint32_t domid,
|
|
unsigned long nr_extents,
|
|
unsigned int extent_order,
|
|
unsigned int address_bits,
|
|
xen_pfn_t *extent_start)
|
|
{
|
|
int err;
|
|
struct xen_memory_reservation reservation = {
|
|
.nr_extents = nr_extents,
|
|
.extent_order = extent_order,
|
|
.address_bits = address_bits,
|
|
.domid = domid
|
|
};
|
|
|
|
/* may be NULL */
|
|
set_xen_guest_handle(reservation.extent_start, extent_start);
|
|
|
|
err = xc_memory_op(xc_handle, XENMEM_increase_reservation, &reservation);
|
|
if ( err == nr_extents )
|
|
return 0;
|
|
|
|
if ( err >= 0 )
|
|
{
|
|
DPRINTF("Failed allocation for dom %d: "
|
|
"%ld extents of order %d, addr_bits %d\n",
|
|
domid, nr_extents, extent_order, address_bits);
|
|
errno = ENOMEM;
|
|
err = -1;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
int xc_domain_memory_decrease_reservation(int xc_handle,
|
|
uint32_t domid,
|
|
unsigned long nr_extents,
|
|
unsigned int extent_order,
|
|
xen_pfn_t *extent_start)
|
|
{
|
|
int err;
|
|
struct xen_memory_reservation reservation = {
|
|
.nr_extents = nr_extents,
|
|
.extent_order = extent_order,
|
|
.address_bits = 0,
|
|
.domid = domid
|
|
};
|
|
|
|
set_xen_guest_handle(reservation.extent_start, extent_start);
|
|
|
|
if ( extent_start == NULL )
|
|
{
|
|
DPRINTF("decrease_reservation extent_start is NULL!\n");
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
err = xc_memory_op(xc_handle, XENMEM_decrease_reservation, &reservation);
|
|
if ( err == nr_extents )
|
|
return 0;
|
|
|
|
if ( err >= 0 )
|
|
{
|
|
DPRINTF("Failed deallocation for dom %d: %ld extents of order %d\n",
|
|
domid, nr_extents, extent_order);
|
|
errno = EINVAL;
|
|
err = -1;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
int xc_domain_memory_populate_physmap(int xc_handle,
|
|
uint32_t domid,
|
|
unsigned long nr_extents,
|
|
unsigned int extent_order,
|
|
unsigned int address_bits,
|
|
xen_pfn_t *extent_start)
|
|
{
|
|
int err;
|
|
struct xen_memory_reservation reservation = {
|
|
.nr_extents = nr_extents,
|
|
.extent_order = extent_order,
|
|
.address_bits = address_bits,
|
|
.domid = domid
|
|
};
|
|
set_xen_guest_handle(reservation.extent_start, extent_start);
|
|
|
|
err = xc_memory_op(xc_handle, XENMEM_populate_physmap, &reservation);
|
|
if ( err == nr_extents )
|
|
return 0;
|
|
|
|
if ( err >= 0 )
|
|
{
|
|
DPRINTF("Failed allocation for dom %d: %ld extents of order %d\n",
|
|
domid, nr_extents, extent_order);
|
|
errno = EBUSY;
|
|
err = -1;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
int xc_domain_max_vcpus(int xc_handle, uint32_t domid, unsigned int max)
|
|
{
|
|
DECLARE_DOMCTL;
|
|
domctl.cmd = XEN_DOMCTL_max_vcpus;
|
|
domctl.domain = (domid_t)domid;
|
|
domctl.u.max_vcpus.max = max;
|
|
return do_domctl(xc_handle, &domctl);
|
|
}
|
|
|
|
int xc_domain_sethandle(int xc_handle, uint32_t domid,
|
|
xen_domain_handle_t handle)
|
|
{
|
|
DECLARE_DOMCTL;
|
|
domctl.cmd = XEN_DOMCTL_setdomainhandle;
|
|
domctl.domain = (domid_t)domid;
|
|
memcpy(domctl.u.setdomainhandle.handle, handle,
|
|
sizeof(xen_domain_handle_t));
|
|
return do_domctl(xc_handle, &domctl);
|
|
}
|
|
|
|
int xc_vcpu_getinfo(int xc_handle,
|
|
uint32_t domid,
|
|
uint32_t vcpu,
|
|
xc_vcpuinfo_t *info)
|
|
{
|
|
int rc;
|
|
DECLARE_DOMCTL;
|
|
|
|
domctl.cmd = XEN_DOMCTL_getvcpuinfo;
|
|
domctl.domain = (domid_t)domid;
|
|
domctl.u.getvcpuinfo.vcpu = (uint16_t)vcpu;
|
|
|
|
rc = do_domctl(xc_handle, &domctl);
|
|
|
|
memcpy(info, &domctl.u.getvcpuinfo, sizeof(*info));
|
|
|
|
return rc;
|
|
}
|
|
|
|
int xc_domain_ioport_permission(int xc_handle,
|
|
uint32_t domid,
|
|
uint32_t first_port,
|
|
uint32_t nr_ports,
|
|
uint32_t allow_access)
|
|
{
|
|
DECLARE_DOMCTL;
|
|
|
|
domctl.cmd = XEN_DOMCTL_ioport_permission;
|
|
domctl.domain = (domid_t)domid;
|
|
domctl.u.ioport_permission.first_port = first_port;
|
|
domctl.u.ioport_permission.nr_ports = nr_ports;
|
|
domctl.u.ioport_permission.allow_access = allow_access;
|
|
|
|
return do_domctl(xc_handle, &domctl);
|
|
}
|
|
|
|
int xc_availheap(int xc_handle,
|
|
int min_width,
|
|
int max_width,
|
|
int node,
|
|
uint64_t *bytes)
|
|
{
|
|
DECLARE_SYSCTL;
|
|
int rc;
|
|
|
|
sysctl.cmd = XEN_SYSCTL_availheap;
|
|
sysctl.u.availheap.min_bitwidth = min_width;
|
|
sysctl.u.availheap.max_bitwidth = max_width;
|
|
sysctl.u.availheap.node = node;
|
|
|
|
rc = xc_sysctl(xc_handle, &sysctl);
|
|
|
|
*bytes = sysctl.u.availheap.avail_bytes;
|
|
|
|
return rc;
|
|
}
|
|
|
|
int xc_vcpu_setcontext(int xc_handle,
|
|
uint32_t domid,
|
|
uint32_t vcpu,
|
|
vcpu_guest_context_t *ctxt)
|
|
{
|
|
DECLARE_DOMCTL;
|
|
int rc;
|
|
size_t sz = sizeof(vcpu_guest_context_either_t);
|
|
|
|
domctl.cmd = XEN_DOMCTL_setvcpucontext;
|
|
domctl.domain = domid;
|
|
domctl.u.vcpucontext.vcpu = vcpu;
|
|
set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt);
|
|
|
|
/*
|
|
* We may be asked to lock either a 32-bit or a 64-bit context. Lock the
|
|
* larger of the two if possible, otherwise fall back to native size.
|
|
*/
|
|
if ( (ctxt != NULL) && (rc = lock_pages(ctxt, sz)) != 0 )
|
|
{
|
|
sz = sizeof(*ctxt);
|
|
if ( (rc = lock_pages(ctxt, sz)) != 0 )
|
|
return rc;
|
|
}
|
|
|
|
rc = do_domctl(xc_handle, &domctl);
|
|
|
|
if ( ctxt != NULL )
|
|
unlock_pages(ctxt, sz);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int xc_domain_irq_permission(int xc_handle,
|
|
uint32_t domid,
|
|
uint8_t pirq,
|
|
uint8_t allow_access)
|
|
{
|
|
DECLARE_DOMCTL;
|
|
|
|
domctl.cmd = XEN_DOMCTL_irq_permission;
|
|
domctl.domain = domid;
|
|
domctl.u.irq_permission.pirq = pirq;
|
|
domctl.u.irq_permission.allow_access = allow_access;
|
|
|
|
return do_domctl(xc_handle, &domctl);
|
|
}
|
|
|
|
int xc_domain_iomem_permission(int xc_handle,
|
|
uint32_t domid,
|
|
unsigned long first_mfn,
|
|
unsigned long nr_mfns,
|
|
uint8_t allow_access)
|
|
{
|
|
DECLARE_DOMCTL;
|
|
|
|
domctl.cmd = XEN_DOMCTL_iomem_permission;
|
|
domctl.domain = domid;
|
|
domctl.u.iomem_permission.first_mfn = first_mfn;
|
|
domctl.u.iomem_permission.nr_mfns = nr_mfns;
|
|
domctl.u.iomem_permission.allow_access = allow_access;
|
|
|
|
return do_domctl(xc_handle, &domctl);
|
|
}
|
|
|
|
int xc_domain_send_trigger(int xc_handle,
|
|
uint32_t domid,
|
|
uint32_t trigger,
|
|
uint32_t vcpu)
|
|
{
|
|
DECLARE_DOMCTL;
|
|
|
|
domctl.cmd = XEN_DOMCTL_sendtrigger;
|
|
domctl.domain = domid;
|
|
domctl.u.sendtrigger.trigger = trigger;
|
|
domctl.u.sendtrigger.vcpu = vcpu;
|
|
|
|
return do_domctl(xc_handle, &domctl);
|
|
}
|
|
|
|
int xc_set_hvm_param(int handle, domid_t dom, int param, unsigned long value)
|
|
{
|
|
DECLARE_HYPERCALL;
|
|
xen_hvm_param_t arg;
|
|
int rc;
|
|
|
|
hypercall.op = __HYPERVISOR_hvm_op;
|
|
hypercall.arg[0] = HVMOP_set_param;
|
|
hypercall.arg[1] = (unsigned long)&arg;
|
|
arg.domid = dom;
|
|
arg.index = param;
|
|
arg.value = value;
|
|
if ( lock_pages(&arg, sizeof(arg)) != 0 )
|
|
return -1;
|
|
rc = do_xen_hypercall(handle, &hypercall);
|
|
unlock_pages(&arg, sizeof(arg));
|
|
return rc;
|
|
}
|
|
|
|
int xc_get_hvm_param(int handle, domid_t dom, int param, unsigned long *value)
|
|
{
|
|
DECLARE_HYPERCALL;
|
|
xen_hvm_param_t arg;
|
|
int rc;
|
|
|
|
hypercall.op = __HYPERVISOR_hvm_op;
|
|
hypercall.arg[0] = HVMOP_get_param;
|
|
hypercall.arg[1] = (unsigned long)&arg;
|
|
arg.domid = dom;
|
|
arg.index = param;
|
|
if ( lock_pages(&arg, sizeof(arg)) != 0 )
|
|
return -1;
|
|
rc = do_xen_hypercall(handle, &hypercall);
|
|
unlock_pages(&arg, sizeof(arg));
|
|
*value = arg.value;
|
|
return rc;
|
|
}
|
|
|
|
int xc_domain_setdebugging(int xc_handle,
|
|
uint32_t domid,
|
|
unsigned int enable)
|
|
{
|
|
DECLARE_DOMCTL;
|
|
|
|
domctl.cmd = XEN_DOMCTL_setdebugging;
|
|
domctl.domain = domid;
|
|
domctl.u.setdebugging.enable = enable;
|
|
return do_domctl(xc_handle, &domctl);
|
|
}
|
|
|
|
int xc_assign_device(
|
|
int xc_handle,
|
|
uint32_t domid,
|
|
uint32_t machine_bdf)
|
|
{
|
|
DECLARE_DOMCTL;
|
|
|
|
domctl.cmd = XEN_DOMCTL_assign_device;
|
|
domctl.domain = domid;
|
|
domctl.u.assign_device.machine_bdf = machine_bdf;
|
|
|
|
return do_domctl(xc_handle, &domctl);
|
|
}
|
|
|
|
int xc_test_assign_device(
|
|
int xc_handle,
|
|
uint32_t domid,
|
|
uint32_t machine_bdf)
|
|
{
|
|
DECLARE_DOMCTL;
|
|
|
|
domctl.cmd = XEN_DOMCTL_test_assign_device;
|
|
domctl.domain = domid;
|
|
domctl.u.assign_device.machine_bdf = machine_bdf;
|
|
|
|
return do_domctl(xc_handle, &domctl);
|
|
}
|
|
|
|
int xc_deassign_device(
|
|
int xc_handle,
|
|
uint32_t domid,
|
|
uint32_t machine_bdf)
|
|
{
|
|
DECLARE_DOMCTL;
|
|
|
|
domctl.cmd = XEN_DOMCTL_deassign_device;
|
|
domctl.domain = domid;
|
|
domctl.u.assign_device.machine_bdf = machine_bdf;
|
|
|
|
return do_domctl(xc_handle, &domctl);
|
|
}
|
|
|
|
/* Pass-through: binds machine irq to guests irq */
|
|
int xc_domain_bind_pt_irq(
|
|
int xc_handle,
|
|
uint32_t domid,
|
|
uint8_t machine_irq,
|
|
uint8_t irq_type,
|
|
uint8_t bus,
|
|
uint8_t device,
|
|
uint8_t intx,
|
|
uint8_t isa_irq)
|
|
{
|
|
int rc;
|
|
xen_domctl_bind_pt_irq_t * bind;
|
|
DECLARE_DOMCTL;
|
|
|
|
domctl.cmd = XEN_DOMCTL_bind_pt_irq;
|
|
domctl.domain = (domid_t)domid;
|
|
|
|
bind = &(domctl.u.bind_pt_irq);
|
|
bind->hvm_domid = domid;
|
|
bind->irq_type = irq_type;
|
|
bind->machine_irq = machine_irq;
|
|
if ( irq_type == PT_IRQ_TYPE_PCI )
|
|
{
|
|
bind->u.pci.bus = bus;
|
|
bind->u.pci.device = device;
|
|
bind->u.pci.intx = intx;
|
|
}
|
|
else if ( irq_type == PT_IRQ_TYPE_ISA )
|
|
bind->u.isa.isa_irq = isa_irq;
|
|
|
|
rc = do_domctl(xc_handle, &domctl);
|
|
return rc;
|
|
}
|
|
|
|
int xc_domain_unbind_pt_irq(
|
|
int xc_handle,
|
|
uint32_t domid,
|
|
uint8_t machine_irq,
|
|
uint8_t irq_type,
|
|
uint8_t bus,
|
|
uint8_t device,
|
|
uint8_t intx,
|
|
uint8_t isa_irq)
|
|
{
|
|
int rc;
|
|
xen_domctl_bind_pt_irq_t * bind;
|
|
DECLARE_DOMCTL;
|
|
|
|
domctl.cmd = XEN_DOMCTL_unbind_pt_irq;
|
|
domctl.domain = (domid_t)domid;
|
|
|
|
bind = &(domctl.u.bind_pt_irq);
|
|
bind->hvm_domid = domid;
|
|
bind->irq_type = irq_type;
|
|
bind->machine_irq = machine_irq;
|
|
bind->u.pci.bus = bus;
|
|
bind->u.pci.device = device;
|
|
bind->u.pci.intx = intx;
|
|
bind->u.isa.isa_irq = isa_irq;
|
|
|
|
rc = do_domctl(xc_handle, &domctl);
|
|
return rc;
|
|
}
|
|
|
|
int xc_domain_bind_pt_pci_irq(
|
|
int xc_handle,
|
|
uint32_t domid,
|
|
uint8_t machine_irq,
|
|
uint8_t bus,
|
|
uint8_t device,
|
|
uint8_t intx)
|
|
{
|
|
|
|
return (xc_domain_bind_pt_irq(xc_handle, domid, machine_irq,
|
|
PT_IRQ_TYPE_PCI, bus, device, intx, 0));
|
|
}
|
|
|
|
int xc_domain_bind_pt_isa_irq(
|
|
int xc_handle,
|
|
uint32_t domid,
|
|
uint8_t machine_irq)
|
|
{
|
|
|
|
return (xc_domain_bind_pt_irq(xc_handle, domid, machine_irq,
|
|
PT_IRQ_TYPE_ISA, 0, 0, 0, machine_irq));
|
|
}
|
|
|
|
int xc_domain_memory_mapping(
|
|
int xc_handle,
|
|
uint32_t domid,
|
|
unsigned long first_gfn,
|
|
unsigned long first_mfn,
|
|
unsigned long nr_mfns,
|
|
uint32_t add_mapping)
|
|
{
|
|
DECLARE_DOMCTL;
|
|
|
|
domctl.cmd = XEN_DOMCTL_memory_mapping;
|
|
domctl.domain = domid;
|
|
domctl.u.memory_mapping.first_gfn = first_gfn;
|
|
domctl.u.memory_mapping.first_mfn = first_mfn;
|
|
domctl.u.memory_mapping.nr_mfns = nr_mfns;
|
|
domctl.u.memory_mapping.add_mapping = add_mapping;
|
|
|
|
return do_domctl(xc_handle, &domctl);
|
|
}
|
|
|
|
int xc_domain_ioport_mapping(
|
|
int xc_handle,
|
|
uint32_t domid,
|
|
uint32_t first_gport,
|
|
uint32_t first_mport,
|
|
uint32_t nr_ports,
|
|
uint32_t add_mapping)
|
|
{
|
|
DECLARE_DOMCTL;
|
|
|
|
domctl.cmd = XEN_DOMCTL_ioport_mapping;
|
|
domctl.domain = domid;
|
|
domctl.u.ioport_mapping.first_gport = first_gport;
|
|
domctl.u.ioport_mapping.first_mport = first_mport;
|
|
domctl.u.ioport_mapping.nr_ports = nr_ports;
|
|
domctl.u.ioport_mapping.add_mapping = add_mapping;
|
|
|
|
return do_domctl(xc_handle, &domctl);
|
|
}
|
|
|
|
int xc_domain_set_target(
|
|
int xc_handle,
|
|
uint32_t domid,
|
|
uint32_t target)
|
|
{
|
|
DECLARE_DOMCTL;
|
|
|
|
domctl.cmd = XEN_DOMCTL_set_target;
|
|
domctl.domain = domid;
|
|
domctl.u.set_target.target = target;
|
|
|
|
return do_domctl(xc_handle, &domctl);
|
|
}
|
|
|
|
/*
|
|
* Local variables:
|
|
* mode: C
|
|
* c-set-style: "BSD"
|
|
* c-basic-offset: 4
|
|
* tab-width: 4
|
|
* indent-tabs-mode: nil
|
|
* End:
|
|
*/
|