xen/privcmd: implement the map resource ioctl
The interface is mostly the same as the Linux ioctl, so that we don't need to modify the user-space libraries that make use of it. The ioctl is just a proxy for the XENMEM_acquire_resource hypercall. Sponsored by: Citrix Systems R&D
This commit is contained in:
parent
147e593921
commit
658860e2d0
@ -372,7 +372,59 @@ privcmd_ioctl(struct cdev *dev, unsigned long cmd, caddr_t arg,
|
||||
|
||||
break;
|
||||
}
|
||||
case IOCTL_PRIVCMD_MMAP_RESOURCE: {
|
||||
struct ioctl_privcmd_mmapresource *mmap;
|
||||
struct xen_mem_acquire_resource adq;
|
||||
xen_pfn_t *gpfns;
|
||||
struct privcmd_map *umap;
|
||||
|
||||
mmap = (struct ioctl_privcmd_mmapresource *)arg;
|
||||
|
||||
bzero(&adq, sizeof(adq));
|
||||
|
||||
adq.domid = mmap->dom;
|
||||
adq.type = mmap->type;
|
||||
adq.id = mmap->id;
|
||||
|
||||
/* Shortcut for getting the resource size. */
|
||||
if (mmap->addr == 0 && mmap->num == 0) {
|
||||
error = HYPERVISOR_memory_op(XENMEM_acquire_resource,
|
||||
&adq);
|
||||
if (error != 0) {
|
||||
error = xen_translate_error(error);
|
||||
break;
|
||||
}
|
||||
error = copyout(&adq.nr_frames, &mmap->num,
|
||||
sizeof(mmap->num));
|
||||
break;
|
||||
}
|
||||
|
||||
umap = setup_virtual_area(td, mmap->addr, mmap->num);
|
||||
if (umap == NULL) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
adq.nr_frames = mmap->num;
|
||||
adq.frame = mmap->idx;
|
||||
|
||||
gpfns = malloc(sizeof(*gpfns) * mmap->num, M_PRIVCMD, M_WAITOK);
|
||||
for (i = 0; i < mmap->num; i++)
|
||||
gpfns[i] = atop(umap->phys_base_addr) + i;
|
||||
set_xen_guest_handle(adq.frame_list, gpfns);
|
||||
|
||||
error = HYPERVISOR_memory_op(XENMEM_acquire_resource, &adq);
|
||||
if (error != 0)
|
||||
error = xen_translate_error(error);
|
||||
else
|
||||
umap->mapped = true;
|
||||
|
||||
free(gpfns, M_PRIVCMD);
|
||||
if (!umap->mapped)
|
||||
free(umap->err, M_PRIVCMD);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
error = ENOSYS;
|
||||
break;
|
||||
|
@ -50,9 +50,24 @@ struct ioctl_privcmd_mmapbatch {
|
||||
int *err; /* array of error codes */
|
||||
};
|
||||
|
||||
struct ioctl_privcmd_mmapresource {
|
||||
domid_t dom; /* target domain */
|
||||
unsigned int type; /* type of resource to map */
|
||||
unsigned int id; /* type-specific resource identifier */
|
||||
unsigned int idx; /* the index of the initial frame to be mapped */
|
||||
unsigned long num; /* number of frames of the resource to be mapped */
|
||||
unsigned long addr; /* physical address to map into */
|
||||
/*
|
||||
* Note: issuing an ioctl with num = addr = 0 will return the size of
|
||||
* the resource.
|
||||
*/
|
||||
};
|
||||
|
||||
#define IOCTL_PRIVCMD_HYPERCALL \
|
||||
_IOWR('E', 0, struct ioctl_privcmd_hypercall)
|
||||
#define IOCTL_PRIVCMD_MMAPBATCH \
|
||||
_IOWR('E', 1, struct ioctl_privcmd_mmapbatch)
|
||||
#define IOCTL_PRIVCMD_MMAP_RESOURCE \
|
||||
_IOW('E', 2, struct ioctl_privcmd_mmapresource)
|
||||
|
||||
#endif /* !__XEN_PRIVCMD_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user