mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
ranges as ro, rw, or mmio_dm. Signed-off-by: Trolle Selander <trolle.selander@eu.citrix.com>
370 lines
8.2 KiB
C
370 lines
8.2 KiB
C
/******************************************************************************
|
|
* xc_misc.c
|
|
*
|
|
* Miscellaneous control interface functions.
|
|
*/
|
|
|
|
#include "xc_private.h"
|
|
#include <xen/hvm/hvm_op.h>
|
|
|
|
int xc_readconsolering(int xc_handle,
|
|
char **pbuffer,
|
|
unsigned int *pnr_chars,
|
|
int clear, int incremental, uint32_t *pindex)
|
|
{
|
|
int ret;
|
|
DECLARE_SYSCTL;
|
|
char *buffer = *pbuffer;
|
|
unsigned int nr_chars = *pnr_chars;
|
|
|
|
sysctl.cmd = XEN_SYSCTL_readconsole;
|
|
set_xen_guest_handle(sysctl.u.readconsole.buffer, buffer);
|
|
sysctl.u.readconsole.count = nr_chars;
|
|
sysctl.u.readconsole.clear = clear;
|
|
sysctl.u.readconsole.incremental = 0;
|
|
if ( pindex )
|
|
{
|
|
sysctl.u.readconsole.index = *pindex;
|
|
sysctl.u.readconsole.incremental = incremental;
|
|
}
|
|
|
|
if ( (ret = lock_pages(buffer, nr_chars)) != 0 )
|
|
return ret;
|
|
|
|
if ( (ret = do_sysctl(xc_handle, &sysctl)) == 0 )
|
|
{
|
|
*pnr_chars = sysctl.u.readconsole.count;
|
|
if ( pindex )
|
|
*pindex = sysctl.u.readconsole.index;
|
|
}
|
|
|
|
unlock_pages(buffer, nr_chars);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int xc_send_debug_keys(int xc_handle, char *keys)
|
|
{
|
|
int ret, len = strlen(keys);
|
|
DECLARE_SYSCTL;
|
|
|
|
sysctl.cmd = XEN_SYSCTL_debug_keys;
|
|
set_xen_guest_handle(sysctl.u.debug_keys.keys, keys);
|
|
sysctl.u.debug_keys.nr_keys = len;
|
|
|
|
if ( (ret = lock_pages(keys, len)) != 0 )
|
|
return ret;
|
|
|
|
ret = do_sysctl(xc_handle, &sysctl);
|
|
|
|
unlock_pages(keys, len);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int xc_physinfo(int xc_handle,
|
|
xc_physinfo_t *put_info)
|
|
{
|
|
int ret;
|
|
DECLARE_SYSCTL;
|
|
|
|
sysctl.cmd = XEN_SYSCTL_physinfo;
|
|
|
|
memcpy(&sysctl.u.physinfo, put_info, sizeof(*put_info));
|
|
|
|
if ( (ret = do_sysctl(xc_handle, &sysctl)) != 0 )
|
|
return ret;
|
|
|
|
memcpy(put_info, &sysctl.u.physinfo, sizeof(*put_info));
|
|
|
|
return 0;
|
|
}
|
|
|
|
int xc_sched_id(int xc_handle,
|
|
int *sched_id)
|
|
{
|
|
int ret;
|
|
DECLARE_SYSCTL;
|
|
|
|
sysctl.cmd = XEN_SYSCTL_sched_id;
|
|
|
|
if ( (ret = do_sysctl(xc_handle, &sysctl)) != 0 )
|
|
return ret;
|
|
|
|
*sched_id = sysctl.u.sched_id.sched_id;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int xc_perfc_control(int xc_handle,
|
|
uint32_t opcode,
|
|
xc_perfc_desc_t *desc,
|
|
xc_perfc_val_t *val,
|
|
int *nbr_desc,
|
|
int *nbr_val)
|
|
{
|
|
int rc;
|
|
DECLARE_SYSCTL;
|
|
|
|
sysctl.cmd = XEN_SYSCTL_perfc_op;
|
|
sysctl.u.perfc_op.cmd = opcode;
|
|
set_xen_guest_handle(sysctl.u.perfc_op.desc, desc);
|
|
set_xen_guest_handle(sysctl.u.perfc_op.val, val);
|
|
|
|
rc = do_sysctl(xc_handle, &sysctl);
|
|
|
|
if ( nbr_desc )
|
|
*nbr_desc = sysctl.u.perfc_op.nr_counters;
|
|
if ( nbr_val )
|
|
*nbr_val = sysctl.u.perfc_op.nr_vals;
|
|
|
|
return rc;
|
|
}
|
|
|
|
int xc_getcpuinfo(int xc_handle, int max_cpus,
|
|
xc_cpuinfo_t *info, int *nr_cpus)
|
|
{
|
|
int rc;
|
|
DECLARE_SYSCTL;
|
|
|
|
sysctl.cmd = XEN_SYSCTL_getcpuinfo;
|
|
sysctl.u.getcpuinfo.max_cpus = max_cpus;
|
|
set_xen_guest_handle(sysctl.u.getcpuinfo.info, info);
|
|
|
|
if ( (rc = lock_pages(info, max_cpus*sizeof(*info))) != 0 )
|
|
return rc;
|
|
|
|
rc = do_sysctl(xc_handle, &sysctl);
|
|
|
|
unlock_pages(info, max_cpus*sizeof(*info));
|
|
|
|
if ( nr_cpus )
|
|
*nr_cpus = sysctl.u.getcpuinfo.nr_cpus;
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
int xc_hvm_set_pci_intx_level(
|
|
int xc_handle, domid_t dom,
|
|
uint8_t domain, uint8_t bus, uint8_t device, uint8_t intx,
|
|
unsigned int level)
|
|
{
|
|
DECLARE_HYPERCALL;
|
|
struct xen_hvm_set_pci_intx_level arg;
|
|
int rc;
|
|
|
|
hypercall.op = __HYPERVISOR_hvm_op;
|
|
hypercall.arg[0] = HVMOP_set_pci_intx_level;
|
|
hypercall.arg[1] = (unsigned long)&arg;
|
|
|
|
arg.domid = dom;
|
|
arg.domain = domain;
|
|
arg.bus = bus;
|
|
arg.device = device;
|
|
arg.intx = intx;
|
|
arg.level = level;
|
|
|
|
if ( (rc = lock_pages(&arg, sizeof(arg))) != 0 )
|
|
{
|
|
PERROR("Could not lock memory");
|
|
return rc;
|
|
}
|
|
|
|
rc = do_xen_hypercall(xc_handle, &hypercall);
|
|
|
|
unlock_pages(&arg, sizeof(arg));
|
|
|
|
return rc;
|
|
}
|
|
|
|
int xc_hvm_set_isa_irq_level(
|
|
int xc_handle, domid_t dom,
|
|
uint8_t isa_irq,
|
|
unsigned int level)
|
|
{
|
|
DECLARE_HYPERCALL;
|
|
struct xen_hvm_set_isa_irq_level arg;
|
|
int rc;
|
|
|
|
hypercall.op = __HYPERVISOR_hvm_op;
|
|
hypercall.arg[0] = HVMOP_set_isa_irq_level;
|
|
hypercall.arg[1] = (unsigned long)&arg;
|
|
|
|
arg.domid = dom;
|
|
arg.isa_irq = isa_irq;
|
|
arg.level = level;
|
|
|
|
if ( (rc = lock_pages(&arg, sizeof(arg))) != 0 )
|
|
{
|
|
PERROR("Could not lock memory");
|
|
return rc;
|
|
}
|
|
|
|
rc = do_xen_hypercall(xc_handle, &hypercall);
|
|
|
|
unlock_pages(&arg, sizeof(arg));
|
|
|
|
return rc;
|
|
}
|
|
|
|
int xc_hvm_set_pci_link_route(
|
|
int xc_handle, domid_t dom, uint8_t link, uint8_t isa_irq)
|
|
{
|
|
DECLARE_HYPERCALL;
|
|
struct xen_hvm_set_pci_link_route arg;
|
|
int rc;
|
|
|
|
hypercall.op = __HYPERVISOR_hvm_op;
|
|
hypercall.arg[0] = HVMOP_set_pci_link_route;
|
|
hypercall.arg[1] = (unsigned long)&arg;
|
|
|
|
arg.domid = dom;
|
|
arg.link = link;
|
|
arg.isa_irq = isa_irq;
|
|
|
|
if ( (rc = lock_pages(&arg, sizeof(arg))) != 0 )
|
|
{
|
|
PERROR("Could not lock memory");
|
|
return rc;
|
|
}
|
|
|
|
rc = do_xen_hypercall(xc_handle, &hypercall);
|
|
|
|
unlock_pages(&arg, sizeof(arg));
|
|
|
|
return rc;
|
|
}
|
|
|
|
int xc_hvm_track_dirty_vram(
|
|
int xc_handle, domid_t dom,
|
|
uint64_t first_pfn, uint64_t nr,
|
|
unsigned long *dirty_bitmap)
|
|
{
|
|
DECLARE_HYPERCALL;
|
|
struct xen_hvm_track_dirty_vram arg;
|
|
int rc;
|
|
|
|
hypercall.op = __HYPERVISOR_hvm_op;
|
|
hypercall.arg[0] = HVMOP_track_dirty_vram;
|
|
hypercall.arg[1] = (unsigned long)&arg;
|
|
|
|
arg.domid = dom;
|
|
arg.first_pfn = first_pfn;
|
|
arg.nr = nr;
|
|
set_xen_guest_handle(arg.dirty_bitmap, (uint8_t *)dirty_bitmap);
|
|
|
|
if ( (rc = lock_pages(&arg, sizeof(arg))) != 0 )
|
|
{
|
|
PERROR("Could not lock memory");
|
|
return rc;
|
|
}
|
|
|
|
rc = do_xen_hypercall(xc_handle, &hypercall);
|
|
|
|
unlock_pages(&arg, sizeof(arg));
|
|
|
|
return rc;
|
|
}
|
|
|
|
int xc_hvm_modified_memory(
|
|
int xc_handle, domid_t dom, uint64_t first_pfn, uint64_t nr)
|
|
{
|
|
DECLARE_HYPERCALL;
|
|
struct xen_hvm_modified_memory arg;
|
|
int rc;
|
|
|
|
hypercall.op = __HYPERVISOR_hvm_op;
|
|
hypercall.arg[0] = HVMOP_modified_memory;
|
|
hypercall.arg[1] = (unsigned long)&arg;
|
|
|
|
arg.domid = dom;
|
|
arg.first_pfn = first_pfn;
|
|
arg.nr = nr;
|
|
|
|
if ( (rc = lock_pages(&arg, sizeof(arg))) != 0 )
|
|
{
|
|
PERROR("Could not lock memory");
|
|
return rc;
|
|
}
|
|
|
|
rc = do_xen_hypercall(xc_handle, &hypercall);
|
|
|
|
unlock_pages(&arg, sizeof(arg));
|
|
|
|
return rc;
|
|
}
|
|
|
|
int xc_hvm_set_mem_type(
|
|
int xc_handle, domid_t dom, hvmmem_type_t mem_type, uint64_t first_pfn, uint64_t nr)
|
|
{
|
|
DECLARE_HYPERCALL;
|
|
struct xen_hvm_set_mem_type arg;
|
|
int rc;
|
|
|
|
hypercall.op = __HYPERVISOR_hvm_op;
|
|
hypercall.arg[0] = HVMOP_set_mem_type;
|
|
hypercall.arg[1] = (unsigned long)&arg;
|
|
|
|
arg.domid = dom;
|
|
arg.hvmmem_type = mem_type;
|
|
arg.first_pfn = first_pfn;
|
|
arg.nr = nr;
|
|
|
|
if ( (rc = lock_pages(&arg, sizeof(arg))) != 0 )
|
|
{
|
|
PERROR("Could not lock memory");
|
|
return rc;
|
|
}
|
|
|
|
rc = do_xen_hypercall(xc_handle, &hypercall);
|
|
|
|
unlock_pages(&arg, sizeof(arg));
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
void *xc_map_foreign_pages(int xc_handle, uint32_t dom, int prot,
|
|
const xen_pfn_t *arr, int num)
|
|
{
|
|
xen_pfn_t *pfn;
|
|
void *res;
|
|
int i;
|
|
|
|
pfn = malloc(num * sizeof(*pfn));
|
|
if (!pfn)
|
|
return NULL;
|
|
memcpy(pfn, arr, num * sizeof(*pfn));
|
|
|
|
res = xc_map_foreign_batch(xc_handle, dom, prot, pfn, num);
|
|
if (res) {
|
|
for (i = 0; i < num; i++) {
|
|
if ((pfn[i] & 0xF0000000UL) == 0xF0000000UL) {
|
|
/*
|
|
* xc_map_foreign_batch() doesn't give us an error
|
|
* code, so we have to make one up. May not be the
|
|
* appropriate one.
|
|
*/
|
|
errno = EINVAL;
|
|
munmap(res, num * PAGE_SIZE);
|
|
res = NULL;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
free(pfn);
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
* Local variables:
|
|
* mode: C
|
|
* c-set-style: "BSD"
|
|
* c-basic-offset: 4
|
|
* tab-width: 4
|
|
* indent-tabs-mode: nil
|
|
* End:
|
|
*/
|