diff options
Diffstat (limited to 'tools/libxc/xc_private.c')
-rw-r--r-- | tools/libxc/xc_private.c | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c new file mode 100644 index 0000000000..344f48254d --- /dev/null +++ b/tools/libxc/xc_private.c @@ -0,0 +1,230 @@ +/****************************************************************************** + * xc_private.c + * + * Helper functions for the rest of the library. + */ + +#include "xc_private.h" + +int init_pfn_mapper(domid_t domid) +{ + int fd = open("/dev/mem", O_RDWR); + if ( fd >= 0 ) + (void)ioctl(fd, _IO('M', 1), (unsigned long)domid); + return fd; +} + +int close_pfn_mapper(int pm_handle) +{ + return close(pm_handle); +} + +void *map_pfn_writeable(int pm_handle, unsigned long pfn) +{ + void *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, + MAP_SHARED, pm_handle, pfn << PAGE_SHIFT); + if ( vaddr == MAP_FAILED ) + return NULL; + return vaddr; +} + +void *map_pfn_readonly(int pm_handle, unsigned long pfn) +{ + void *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ, + MAP_SHARED, pm_handle, pfn << PAGE_SHIFT); + if ( vaddr == MAP_FAILED ) + return NULL; + return vaddr; +} + +void unmap_pfn(int pm_handle, void *vaddr) +{ + (void)munmap(vaddr, PAGE_SIZE); +} + +/*******************/ + +void * mfn_mapper_map_batch(int xc_handle, domid_t dom, int prot, + unsigned long *arr, int num ) +{ + privcmd_mmapbatch_t ioctlx; + void *addr; + addr = mmap( NULL, num*PAGE_SIZE, prot, MAP_SHARED, xc_handle, 0 ); + if (addr) + { + ioctlx.num=num; + ioctlx.dom=dom; + ioctlx.addr=(unsigned long)addr; + ioctlx.arr=arr; + if ( ioctl( xc_handle, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx ) < 0 ) + { + perror("XXXXXXXX"); + munmap(addr, num*PAGE_SIZE); + return 0; + } + } + return addr; + +} + +/*******************/ + +void * mfn_mapper_map_single(int xc_handle, domid_t dom, + int size, int prot, + unsigned long mfn ) +{ + privcmd_mmap_t ioctlx; + privcmd_mmap_entry_t entry; + void *addr; + addr = mmap( NULL, size, prot, MAP_SHARED, xc_handle, 0 ); + if (addr) + { + ioctlx.num=1; + ioctlx.dom=dom; + ioctlx.entry=&entry; + entry.va=(unsigned long) addr; + entry.mfn=mfn; + entry.npages=(size+PAGE_SIZE-1)>>PAGE_SHIFT; + if ( ioctl( xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx ) <0 ) + { + munmap(addr, size); + return 0; + } + } + return addr; +} + +/*******************/ + +/* NB: arr must be mlock'ed */ +int get_pfn_type_batch(int xc_handle, + u32 dom, int num, unsigned long *arr) +{ + dom0_op_t op; + op.cmd = DOM0_GETPAGEFRAMEINFO2; + op.u.getpageframeinfo2.domain = (domid_t)dom; + op.u.getpageframeinfo2.num = num; + op.u.getpageframeinfo2.array = arr; + return do_dom0_op(xc_handle, &op); +} + +#define GETPFN_ERR (~0U) +unsigned int get_pfn_type(int xc_handle, + unsigned long mfn, + u32 dom) +{ + dom0_op_t op; + op.cmd = DOM0_GETPAGEFRAMEINFO; + op.u.getpageframeinfo.pfn = mfn; + op.u.getpageframeinfo.domain = (domid_t)dom; + if ( do_dom0_op(xc_handle, &op) < 0 ) + { + PERROR("Unexpected failure when getting page frame info!"); + return GETPFN_ERR; + } + return op.u.getpageframeinfo.type; +} + + + +/*******************/ + +#define FIRST_MMU_UPDATE 1 + +static int flush_mmu_updates(int xc_handle, mmu_t *mmu) +{ + int err = 0; + privcmd_hypercall_t hypercall; + + if ( mmu->idx == FIRST_MMU_UPDATE ) + return 0; + + /* The first two requests set the correct subject domain (PTS and GPS). */ + mmu->updates[0].val = (unsigned long)(mmu->subject<<16) & ~0xFFFFUL; + mmu->updates[0].ptr = (unsigned long)(mmu->subject<< 0) & ~0xFFFFUL; + mmu->updates[0].ptr |= MMU_EXTENDED_COMMAND; + mmu->updates[0].val |= MMUEXT_SET_SUBJECTDOM | SET_PAGETABLE_SUBJECTDOM; + + hypercall.op = __HYPERVISOR_mmu_update; + hypercall.arg[0] = (unsigned long)mmu->updates; + hypercall.arg[1] = (unsigned long)mmu->idx; + hypercall.arg[2] = 0; + + if ( mlock(mmu->updates, sizeof(mmu->updates)) != 0 ) + { + PERROR("Could not lock pagetable update array"); + err = 1; + goto out; + } + + if ( do_xen_hypercall(xc_handle, &hypercall) < 0 ) + { + ERROR("Failure when submitting mmu updates"); + err = 1; + } + + mmu->idx = FIRST_MMU_UPDATE; + + (void)munlock(mmu->updates, sizeof(mmu->updates)); + + out: + return err; +} + +mmu_t *init_mmu_updates(int xc_handle, domid_t dom) +{ + mmu_t *mmu = malloc(sizeof(mmu_t)); + if ( mmu == NULL ) + return mmu; + mmu->idx = FIRST_MMU_UPDATE; + mmu->subject = dom; + return mmu; +} + +int add_mmu_update(int xc_handle, mmu_t *mmu, + unsigned long ptr, unsigned long val) +{ + mmu->updates[mmu->idx].ptr = ptr; + mmu->updates[mmu->idx].val = val; + + if ( ++mmu->idx == MAX_MMU_UPDATES ) + return flush_mmu_updates(xc_handle, mmu); + + return 0; +} + +int finish_mmu_updates(int xc_handle, mmu_t *mmu) +{ + return flush_mmu_updates(xc_handle, mmu); +} + + +long long xc_domain_get_cpu_usage( int xc_handle, domid_t domid ) +{ + dom0_op_t op; + + op.cmd = DOM0_GETDOMAININFO; + op.u.getdomaininfo.domain = (domid_t)domid; + op.u.getdomaininfo.ctxt = NULL; + if ( (do_dom0_op(xc_handle, &op) < 0) || + ((u32)op.u.getdomaininfo.domain != domid) ) + { + PERROR("Could not get info on domain"); + return -1; + } + return op.u.getdomaininfo.cpu_time; +} + + +/* This is shared between save and restore, and may generally be useful. */ +unsigned long csum_page (void * page) +{ + int i; + unsigned long *p = page; + unsigned long long sum=0; + + for ( i = 0; i < (PAGE_SIZE/sizeof(unsigned long)); i++ ) + sum += p[i]; + + return sum ^ (sum>>32); +} |