diff options
author | Roger Pau Monne <roger.pau@citrix.com> | 2020-06-23 09:36:19 +0000 |
---|---|---|
committer | Roger Pau Monné <royger@FreeBSD.org> | 2021-01-11 15:15:00 +0000 |
commit | 658860e2d07065b4203bb3e7779bee0512c65c92 (patch) | |
tree | b2be1c973a57671b87fafbfd9366ca4775acee73 /sys/dev/xen | |
parent | 147e593921d7b9a6697a92a512ab7bd777f9a6b1 (diff) | |
download | src-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.c | 52 |
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; |