aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/xen
diff options
context:
space:
mode:
authorRoger Pau Monne <roger.pau@citrix.com>2020-06-23 09:36:19 +0000
committerRoger Pau Monné <royger@FreeBSD.org>2021-01-11 15:15:00 +0000
commit658860e2d07065b4203bb3e7779bee0512c65c92 (patch)
treeb2be1c973a57671b87fafbfd9366ca4775acee73 /sys/dev/xen
parent147e593921d7b9a6697a92a512ab7bd777f9a6b1 (diff)
downloadsrc-658860e2d07065b4203bb3e7779bee0512c65c92.tar.gz
src-658860e2d07065b4203bb3e7779bee0512c65c92.zip
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
Diffstat (limited to 'sys/dev/xen')
-rw-r--r--sys/dev/xen/privcmd/privcmd.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/sys/dev/xen/privcmd/privcmd.c b/sys/dev/xen/privcmd/privcmd.c
index 78fb32444931..c31c31bcfe41 100644
--- a/sys/dev/xen/privcmd/privcmd.c
+++ b/sys/dev/xen/privcmd/privcmd.c
@@ -372,7 +372,59 @@ mmap_out:
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;