9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <linux/sched.h>
12 #include <linux/slab.h>
13 #include <linux/string.h>
14 #include <linux/errno.h>
16 #include <linux/mman.h>
24 #include <asm/pgalloc.h>
25 #include <asm/pgtable.h>
27 #include <asm/xen/hypervisor.h>
28 #include <asm/xen/hypercall.h>
31 #include <xen/privcmd.h>
35 #include <xen/xen-ops.h>
41 #ifndef HAVE_ARCH_PRIVCMD_MMAP
42 static int privcmd_enforce_singleshot_mapping(
struct vm_area_struct *vma);
45 static long privcmd_ioctl_hypercall(
void __user *udata)
54 hypercall.arg[0], hypercall.arg[1],
55 hypercall.arg[2], hypercall.arg[3],
68 INIT_LIST_HEAD(pages);
122 static int traverse_pages(
unsigned nelem,
size_t size,
124 int (*
fn)(
void *data,
void *
state),
145 ret = (*fn)(pagedata + pageidx,
state);
160 static int mmap_mfn_range(
void *data,
void *state)
173 if ((msg->
va != st->
va) ||
190 static long privcmd_ioctl_mmap(
void __user *udata)
205 rc = gather_array(&pagelist,
209 if (rc || list_empty(&pagelist))
223 !privcmd_enforce_singleshot_mapping(vma))
229 state.domain = mmapcmd.dom;
233 mmap_mfn_range, &state);
240 free_page_list(&pagelist);
263 static int mmap_batch_fn(
void *data,
void *state)
290 static int mmap_return_errors_v1(
void *data,
void *state)
300 *mfnp |= (err == -
ENOENT) ?
306 static struct vm_operations_struct privcmd_vm_ops;
308 static long privcmd_ioctl_mmap_batch(
void __user *udata,
int version)
314 unsigned long nr_pages;
316 int *err_array =
NULL;
346 ret = gather_array(&pagelist,
m.num,
sizeof(
xen_pfn_t),
m.arr);
350 if (list_empty(&pagelist)) {
355 err_array = kcalloc(
m.num,
sizeof(
int),
GFP_KERNEL);
356 if (err_array ==
NULL) {
365 vma->
vm_ops != &privcmd_vm_ops ||
368 !privcmd_enforce_singleshot_mapping(vma)) {
374 state.domain =
m.dom;
377 state.global_error = 0;
378 state.err = err_array;
382 &pagelist, mmap_batch_fn, &state));
387 if (state.global_error) {
390 state.err = err_array;
391 ret = traverse_pages(
m.num,
sizeof(
xen_pfn_t),
392 &pagelist, mmap_return_errors_v1, &
state);
396 }
else if (version == 2) {
404 if ((ret == 0) && (state.global_error == -
ENOENT))
409 free_page_list(&pagelist);
414 static long privcmd_ioctl(
struct file *
file,
415 unsigned int cmd,
unsigned long data)
422 ret = privcmd_ioctl_hypercall(udata);
426 ret = privcmd_ioctl_mmap(udata);
430 ret = privcmd_ioctl_mmap_batch(udata, 1);
434 ret = privcmd_ioctl_mmap_batch(udata, 2);
445 static int privcmd_fault(
struct vm_area_struct *vma,
struct vm_fault *vmf)
449 vmf->pgoff, vmf->virtual_address);
451 return VM_FAULT_SIGBUS;
454 static struct vm_operations_struct privcmd_vm_ops = {
455 .fault = privcmd_fault
462 vma->
vm_flags |= VM_IO | VM_PFNMAP | VM_DONTCOPY |
463 VM_DONTEXPAND | VM_DONTDUMP;
464 vma->
vm_ops = &privcmd_vm_ops;
470 static int privcmd_enforce_singleshot_mapping(
struct vm_area_struct *vma)
477 .unlocked_ioctl = privcmd_ioctl,
484 .name =
"xen/privcmd",
488 static int __init privcmd_init(
void)
503 static void __exit privcmd_exit(
void)