diff options
-rw-r--r-- | arch/arm/xen/enlighten.c | 11 | ||||
-rw-r--r-- | arch/x86/xen/mmu.c | 60 | ||||
-rw-r--r-- | drivers/xen/privcmd.c | 133 | ||||
-rw-r--r-- | include/uapi/xen/privcmd.h | 11 | ||||
-rw-r--r-- | include/xen/interface/memory.h | 66 | ||||
-rw-r--r-- | include/xen/interface/xen.h | 7 | ||||
-rw-r--r-- | include/xen/xen-ops.h | 24 |
7 files changed, 291 insertions, 21 deletions
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c index ba7f4c8f5c3e..8073625371f5 100644 --- a/arch/arm/xen/enlighten.c +++ b/arch/arm/xen/enlighten.c | |||
@@ -89,6 +89,17 @@ int xen_unmap_domain_gfn_range(struct vm_area_struct *vma, | |||
89 | } | 89 | } |
90 | EXPORT_SYMBOL_GPL(xen_unmap_domain_gfn_range); | 90 | EXPORT_SYMBOL_GPL(xen_unmap_domain_gfn_range); |
91 | 91 | ||
92 | /* Not used by XENFEAT_auto_translated guests. */ | ||
93 | int xen_remap_domain_mfn_array(struct vm_area_struct *vma, | ||
94 | unsigned long addr, | ||
95 | xen_pfn_t *mfn, int nr, | ||
96 | int *err_ptr, pgprot_t prot, | ||
97 | unsigned int domid, struct page **pages) | ||
98 | { | ||
99 | return -ENOSYS; | ||
100 | } | ||
101 | EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_array); | ||
102 | |||
92 | static void xen_read_wallclock(struct timespec64 *ts) | 103 | static void xen_read_wallclock(struct timespec64 *ts) |
93 | { | 104 | { |
94 | u32 version; | 105 | u32 version; |
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index d33e7dbe3129..af2960cb7a3e 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
@@ -65,37 +65,44 @@ static void xen_flush_tlb_all(void) | |||
65 | #define REMAP_BATCH_SIZE 16 | 65 | #define REMAP_BATCH_SIZE 16 |
66 | 66 | ||
67 | struct remap_data { | 67 | struct remap_data { |
68 | xen_pfn_t *mfn; | 68 | xen_pfn_t *pfn; |
69 | bool contiguous; | 69 | bool contiguous; |
70 | bool no_translate; | ||
70 | pgprot_t prot; | 71 | pgprot_t prot; |
71 | struct mmu_update *mmu_update; | 72 | struct mmu_update *mmu_update; |
72 | }; | 73 | }; |
73 | 74 | ||
74 | static int remap_area_mfn_pte_fn(pte_t *ptep, pgtable_t token, | 75 | static int remap_area_pfn_pte_fn(pte_t *ptep, pgtable_t token, |
75 | unsigned long addr, void *data) | 76 | unsigned long addr, void *data) |
76 | { | 77 | { |
77 | struct remap_data *rmd = data; | 78 | struct remap_data *rmd = data; |
78 | pte_t pte = pte_mkspecial(mfn_pte(*rmd->mfn, rmd->prot)); | 79 | pte_t pte = pte_mkspecial(mfn_pte(*rmd->pfn, rmd->prot)); |
79 | 80 | ||
80 | /* If we have a contiguous range, just update the mfn itself, | 81 | /* |
81 | else update pointer to be "next mfn". */ | 82 | * If we have a contiguous range, just update the pfn itself, |
83 | * else update pointer to be "next pfn". | ||
84 | */ | ||
82 | if (rmd->contiguous) | 85 | if (rmd->contiguous) |
83 | (*rmd->mfn)++; | 86 | (*rmd->pfn)++; |
84 | else | 87 | else |
85 | rmd->mfn++; | 88 | rmd->pfn++; |
86 | 89 | ||
87 | rmd->mmu_update->ptr = virt_to_machine(ptep).maddr | MMU_NORMAL_PT_UPDATE; | 90 | rmd->mmu_update->ptr = virt_to_machine(ptep).maddr; |
91 | rmd->mmu_update->ptr |= rmd->no_translate ? | ||
92 | MMU_PT_UPDATE_NO_TRANSLATE : | ||
93 | MMU_NORMAL_PT_UPDATE; | ||
88 | rmd->mmu_update->val = pte_val_ma(pte); | 94 | rmd->mmu_update->val = pte_val_ma(pte); |
89 | rmd->mmu_update++; | 95 | rmd->mmu_update++; |
90 | 96 | ||
91 | return 0; | 97 | return 0; |
92 | } | 98 | } |
93 | 99 | ||
94 | static int do_remap_gfn(struct vm_area_struct *vma, | 100 | static int do_remap_pfn(struct vm_area_struct *vma, |
95 | unsigned long addr, | 101 | unsigned long addr, |
96 | xen_pfn_t *gfn, int nr, | 102 | xen_pfn_t *pfn, int nr, |
97 | int *err_ptr, pgprot_t prot, | 103 | int *err_ptr, pgprot_t prot, |
98 | unsigned domid, | 104 | unsigned int domid, |
105 | bool no_translate, | ||
99 | struct page **pages) | 106 | struct page **pages) |
100 | { | 107 | { |
101 | int err = 0; | 108 | int err = 0; |
@@ -106,11 +113,14 @@ static int do_remap_gfn(struct vm_area_struct *vma, | |||
106 | 113 | ||
107 | BUG_ON(!((vma->vm_flags & (VM_PFNMAP | VM_IO)) == (VM_PFNMAP | VM_IO))); | 114 | BUG_ON(!((vma->vm_flags & (VM_PFNMAP | VM_IO)) == (VM_PFNMAP | VM_IO))); |
108 | 115 | ||
109 | rmd.mfn = gfn; | 116 | rmd.pfn = pfn; |
110 | rmd.prot = prot; | 117 | rmd.prot = prot; |
111 | /* We use the err_ptr to indicate if there we are doing a contiguous | 118 | /* |
112 | * mapping or a discontigious mapping. */ | 119 | * We use the err_ptr to indicate if there we are doing a contiguous |
120 | * mapping or a discontigious mapping. | ||
121 | */ | ||
113 | rmd.contiguous = !err_ptr; | 122 | rmd.contiguous = !err_ptr; |
123 | rmd.no_translate = no_translate; | ||
114 | 124 | ||
115 | while (nr) { | 125 | while (nr) { |
116 | int index = 0; | 126 | int index = 0; |
@@ -121,7 +131,7 @@ static int do_remap_gfn(struct vm_area_struct *vma, | |||
121 | 131 | ||
122 | rmd.mmu_update = mmu_update; | 132 | rmd.mmu_update = mmu_update; |
123 | err = apply_to_page_range(vma->vm_mm, addr, range, | 133 | err = apply_to_page_range(vma->vm_mm, addr, range, |
124 | remap_area_mfn_pte_fn, &rmd); | 134 | remap_area_pfn_pte_fn, &rmd); |
125 | if (err) | 135 | if (err) |
126 | goto out; | 136 | goto out; |
127 | 137 | ||
@@ -175,7 +185,8 @@ int xen_remap_domain_gfn_range(struct vm_area_struct *vma, | |||
175 | if (xen_feature(XENFEAT_auto_translated_physmap)) | 185 | if (xen_feature(XENFEAT_auto_translated_physmap)) |
176 | return -EOPNOTSUPP; | 186 | return -EOPNOTSUPP; |
177 | 187 | ||
178 | return do_remap_gfn(vma, addr, &gfn, nr, NULL, prot, domid, pages); | 188 | return do_remap_pfn(vma, addr, &gfn, nr, NULL, prot, domid, false, |
189 | pages); | ||
179 | } | 190 | } |
180 | EXPORT_SYMBOL_GPL(xen_remap_domain_gfn_range); | 191 | EXPORT_SYMBOL_GPL(xen_remap_domain_gfn_range); |
181 | 192 | ||
@@ -194,10 +205,25 @@ int xen_remap_domain_gfn_array(struct vm_area_struct *vma, | |||
194 | * cause of "wrong memory was mapped in". | 205 | * cause of "wrong memory was mapped in". |
195 | */ | 206 | */ |
196 | BUG_ON(err_ptr == NULL); | 207 | BUG_ON(err_ptr == NULL); |
197 | return do_remap_gfn(vma, addr, gfn, nr, err_ptr, prot, domid, pages); | 208 | return do_remap_pfn(vma, addr, gfn, nr, err_ptr, prot, domid, |
209 | false, pages); | ||
198 | } | 210 | } |
199 | EXPORT_SYMBOL_GPL(xen_remap_domain_gfn_array); | 211 | EXPORT_SYMBOL_GPL(xen_remap_domain_gfn_array); |
200 | 212 | ||
213 | int xen_remap_domain_mfn_array(struct vm_area_struct *vma, | ||
214 | unsigned long addr, | ||
215 | xen_pfn_t *mfn, int nr, | ||
216 | int *err_ptr, pgprot_t prot, | ||
217 | unsigned int domid, struct page **pages) | ||
218 | { | ||
219 | if (xen_feature(XENFEAT_auto_translated_physmap)) | ||
220 | return -EOPNOTSUPP; | ||
221 | |||
222 | return do_remap_pfn(vma, addr, mfn, nr, err_ptr, prot, domid, | ||
223 | true, pages); | ||
224 | } | ||
225 | EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_array); | ||
226 | |||
201 | /* Returns: 0 success */ | 227 | /* Returns: 0 success */ |
202 | int xen_unmap_domain_gfn_range(struct vm_area_struct *vma, | 228 | int xen_unmap_domain_gfn_range(struct vm_area_struct *vma, |
203 | int nr, struct page **pages) | 229 | int nr, struct page **pages) |
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c index 0a778d30d333..8ae0349d9f0a 100644 --- a/drivers/xen/privcmd.c +++ b/drivers/xen/privcmd.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <xen/xen.h> | 33 | #include <xen/xen.h> |
34 | #include <xen/privcmd.h> | 34 | #include <xen/privcmd.h> |
35 | #include <xen/interface/xen.h> | 35 | #include <xen/interface/xen.h> |
36 | #include <xen/interface/memory.h> | ||
36 | #include <xen/interface/hvm/dm_op.h> | 37 | #include <xen/interface/hvm/dm_op.h> |
37 | #include <xen/features.h> | 38 | #include <xen/features.h> |
38 | #include <xen/page.h> | 39 | #include <xen/page.h> |
@@ -722,6 +723,134 @@ static long privcmd_ioctl_restrict(struct file *file, void __user *udata) | |||
722 | return 0; | 723 | return 0; |
723 | } | 724 | } |
724 | 725 | ||
726 | struct remap_pfn { | ||
727 | struct mm_struct *mm; | ||
728 | struct page **pages; | ||
729 | pgprot_t prot; | ||
730 | unsigned long i; | ||
731 | }; | ||
732 | |||
733 | static int remap_pfn_fn(pte_t *ptep, pgtable_t token, unsigned long addr, | ||
734 | void *data) | ||
735 | { | ||
736 | struct remap_pfn *r = data; | ||
737 | struct page *page = r->pages[r->i]; | ||
738 | pte_t pte = pte_mkspecial(pfn_pte(page_to_pfn(page), r->prot)); | ||
739 | |||
740 | set_pte_at(r->mm, addr, ptep, pte); | ||
741 | r->i++; | ||
742 | |||
743 | return 0; | ||
744 | } | ||
745 | |||
746 | static long privcmd_ioctl_mmap_resource(struct file *file, void __user *udata) | ||
747 | { | ||
748 | struct privcmd_data *data = file->private_data; | ||
749 | struct mm_struct *mm = current->mm; | ||
750 | struct vm_area_struct *vma; | ||
751 | struct privcmd_mmap_resource kdata; | ||
752 | xen_pfn_t *pfns = NULL; | ||
753 | struct xen_mem_acquire_resource xdata; | ||
754 | int rc; | ||
755 | |||
756 | if (copy_from_user(&kdata, udata, sizeof(kdata))) | ||
757 | return -EFAULT; | ||
758 | |||
759 | /* If restriction is in place, check the domid matches */ | ||
760 | if (data->domid != DOMID_INVALID && data->domid != kdata.dom) | ||
761 | return -EPERM; | ||
762 | |||
763 | down_write(&mm->mmap_sem); | ||
764 | |||
765 | vma = find_vma(mm, kdata.addr); | ||
766 | if (!vma || vma->vm_ops != &privcmd_vm_ops) { | ||
767 | rc = -EINVAL; | ||
768 | goto out; | ||
769 | } | ||
770 | |||
771 | pfns = kcalloc(kdata.num, sizeof(*pfns), GFP_KERNEL); | ||
772 | if (!pfns) { | ||
773 | rc = -ENOMEM; | ||
774 | goto out; | ||
775 | } | ||
776 | |||
777 | if (xen_feature(XENFEAT_auto_translated_physmap)) { | ||
778 | unsigned int nr = DIV_ROUND_UP(kdata.num, XEN_PFN_PER_PAGE); | ||
779 | struct page **pages; | ||
780 | unsigned int i; | ||
781 | |||
782 | rc = alloc_empty_pages(vma, nr); | ||
783 | if (rc < 0) | ||
784 | goto out; | ||
785 | |||
786 | pages = vma->vm_private_data; | ||
787 | for (i = 0; i < kdata.num; i++) { | ||
788 | xen_pfn_t pfn = | ||
789 | page_to_xen_pfn(pages[i / XEN_PFN_PER_PAGE]); | ||
790 | |||
791 | pfns[i] = pfn + (i % XEN_PFN_PER_PAGE); | ||
792 | } | ||
793 | } else | ||
794 | vma->vm_private_data = PRIV_VMA_LOCKED; | ||
795 | |||
796 | memset(&xdata, 0, sizeof(xdata)); | ||
797 | xdata.domid = kdata.dom; | ||
798 | xdata.type = kdata.type; | ||
799 | xdata.id = kdata.id; | ||
800 | xdata.frame = kdata.idx; | ||
801 | xdata.nr_frames = kdata.num; | ||
802 | set_xen_guest_handle(xdata.frame_list, pfns); | ||
803 | |||
804 | xen_preemptible_hcall_begin(); | ||
805 | rc = HYPERVISOR_memory_op(XENMEM_acquire_resource, &xdata); | ||
806 | xen_preemptible_hcall_end(); | ||
807 | |||
808 | if (rc) | ||
809 | goto out; | ||
810 | |||
811 | if (xen_feature(XENFEAT_auto_translated_physmap)) { | ||
812 | struct remap_pfn r = { | ||
813 | .mm = vma->vm_mm, | ||
814 | .pages = vma->vm_private_data, | ||
815 | .prot = vma->vm_page_prot, | ||
816 | }; | ||
817 | |||
818 | rc = apply_to_page_range(r.mm, kdata.addr, | ||
819 | kdata.num << PAGE_SHIFT, | ||
820 | remap_pfn_fn, &r); | ||
821 | } else { | ||
822 | unsigned int domid = | ||
823 | (xdata.flags & XENMEM_rsrc_acq_caller_owned) ? | ||
824 | DOMID_SELF : kdata.dom; | ||
825 | int num; | ||
826 | |||
827 | num = xen_remap_domain_mfn_array(vma, | ||
828 | kdata.addr & PAGE_MASK, | ||
829 | pfns, kdata.num, (int *)pfns, | ||
830 | vma->vm_page_prot, | ||
831 | domid, | ||
832 | vma->vm_private_data); | ||
833 | if (num < 0) | ||
834 | rc = num; | ||
835 | else if (num != kdata.num) { | ||
836 | unsigned int i; | ||
837 | |||
838 | for (i = 0; i < num; i++) { | ||
839 | rc = pfns[i]; | ||
840 | if (rc < 0) | ||
841 | break; | ||
842 | } | ||
843 | } else | ||
844 | rc = 0; | ||
845 | } | ||
846 | |||
847 | out: | ||
848 | up_write(&mm->mmap_sem); | ||
849 | kfree(pfns); | ||
850 | |||
851 | return rc; | ||
852 | } | ||
853 | |||
725 | static long privcmd_ioctl(struct file *file, | 854 | static long privcmd_ioctl(struct file *file, |
726 | unsigned int cmd, unsigned long data) | 855 | unsigned int cmd, unsigned long data) |
727 | { | 856 | { |
@@ -753,6 +882,10 @@ static long privcmd_ioctl(struct file *file, | |||
753 | ret = privcmd_ioctl_restrict(file, udata); | 882 | ret = privcmd_ioctl_restrict(file, udata); |
754 | break; | 883 | break; |
755 | 884 | ||
885 | case IOCTL_PRIVCMD_MMAP_RESOURCE: | ||
886 | ret = privcmd_ioctl_mmap_resource(file, udata); | ||
887 | break; | ||
888 | |||
756 | default: | 889 | default: |
757 | break; | 890 | break; |
758 | } | 891 | } |
diff --git a/include/uapi/xen/privcmd.h b/include/uapi/xen/privcmd.h index 39d3e7b8e993..d2029556083e 100644 --- a/include/uapi/xen/privcmd.h +++ b/include/uapi/xen/privcmd.h | |||
@@ -89,6 +89,15 @@ struct privcmd_dm_op { | |||
89 | const struct privcmd_dm_op_buf __user *ubufs; | 89 | const struct privcmd_dm_op_buf __user *ubufs; |
90 | }; | 90 | }; |
91 | 91 | ||
92 | struct privcmd_mmap_resource { | ||
93 | domid_t dom; | ||
94 | __u32 type; | ||
95 | __u32 id; | ||
96 | __u32 idx; | ||
97 | __u64 num; | ||
98 | __u64 addr; | ||
99 | }; | ||
100 | |||
92 | /* | 101 | /* |
93 | * @cmd: IOCTL_PRIVCMD_HYPERCALL | 102 | * @cmd: IOCTL_PRIVCMD_HYPERCALL |
94 | * @arg: &privcmd_hypercall_t | 103 | * @arg: &privcmd_hypercall_t |
@@ -114,5 +123,7 @@ struct privcmd_dm_op { | |||
114 | _IOC(_IOC_NONE, 'P', 5, sizeof(struct privcmd_dm_op)) | 123 | _IOC(_IOC_NONE, 'P', 5, sizeof(struct privcmd_dm_op)) |
115 | #define IOCTL_PRIVCMD_RESTRICT \ | 124 | #define IOCTL_PRIVCMD_RESTRICT \ |
116 | _IOC(_IOC_NONE, 'P', 6, sizeof(domid_t)) | 125 | _IOC(_IOC_NONE, 'P', 6, sizeof(domid_t)) |
126 | #define IOCTL_PRIVCMD_MMAP_RESOURCE \ | ||
127 | _IOC(_IOC_NONE, 'P', 7, sizeof(struct privcmd_mmap_resource)) | ||
117 | 128 | ||
118 | #endif /* __LINUX_PUBLIC_PRIVCMD_H__ */ | 129 | #endif /* __LINUX_PUBLIC_PRIVCMD_H__ */ |
diff --git a/include/xen/interface/memory.h b/include/xen/interface/memory.h index 583dd93b3016..4c5751c26f87 100644 --- a/include/xen/interface/memory.h +++ b/include/xen/interface/memory.h | |||
@@ -265,4 +265,70 @@ struct xen_remove_from_physmap { | |||
265 | }; | 265 | }; |
266 | DEFINE_GUEST_HANDLE_STRUCT(xen_remove_from_physmap); | 266 | DEFINE_GUEST_HANDLE_STRUCT(xen_remove_from_physmap); |
267 | 267 | ||
268 | /* | ||
269 | * Get the pages for a particular guest resource, so that they can be | ||
270 | * mapped directly by a tools domain. | ||
271 | */ | ||
272 | #define XENMEM_acquire_resource 28 | ||
273 | struct xen_mem_acquire_resource { | ||
274 | /* IN - The domain whose resource is to be mapped */ | ||
275 | domid_t domid; | ||
276 | /* IN - the type of resource */ | ||
277 | uint16_t type; | ||
278 | |||
279 | #define XENMEM_resource_ioreq_server 0 | ||
280 | #define XENMEM_resource_grant_table 1 | ||
281 | |||
282 | /* | ||
283 | * IN - a type-specific resource identifier, which must be zero | ||
284 | * unless stated otherwise. | ||
285 | * | ||
286 | * type == XENMEM_resource_ioreq_server -> id == ioreq server id | ||
287 | * type == XENMEM_resource_grant_table -> id defined below | ||
288 | */ | ||
289 | uint32_t id; | ||
290 | |||
291 | #define XENMEM_resource_grant_table_id_shared 0 | ||
292 | #define XENMEM_resource_grant_table_id_status 1 | ||
293 | |||
294 | /* IN/OUT - As an IN parameter number of frames of the resource | ||
295 | * to be mapped. However, if the specified value is 0 and | ||
296 | * frame_list is NULL then this field will be set to the | ||
297 | * maximum value supported by the implementation on return. | ||
298 | */ | ||
299 | uint32_t nr_frames; | ||
300 | /* | ||
301 | * OUT - Must be zero on entry. On return this may contain a bitwise | ||
302 | * OR of the following values. | ||
303 | */ | ||
304 | uint32_t flags; | ||
305 | |||
306 | /* The resource pages have been assigned to the calling domain */ | ||
307 | #define _XENMEM_rsrc_acq_caller_owned 0 | ||
308 | #define XENMEM_rsrc_acq_caller_owned (1u << _XENMEM_rsrc_acq_caller_owned) | ||
309 | |||
310 | /* | ||
311 | * IN - the index of the initial frame to be mapped. This parameter | ||
312 | * is ignored if nr_frames is 0. | ||
313 | */ | ||
314 | uint64_t frame; | ||
315 | |||
316 | #define XENMEM_resource_ioreq_server_frame_bufioreq 0 | ||
317 | #define XENMEM_resource_ioreq_server_frame_ioreq(n) (1 + (n)) | ||
318 | |||
319 | /* | ||
320 | * IN/OUT - If the tools domain is PV then, upon return, frame_list | ||
321 | * will be populated with the MFNs of the resource. | ||
322 | * If the tools domain is HVM then it is expected that, on | ||
323 | * entry, frame_list will be populated with a list of GFNs | ||
324 | * that will be mapped to the MFNs of the resource. | ||
325 | * If -EIO is returned then the frame_list has only been | ||
326 | * partially mapped and it is up to the caller to unmap all | ||
327 | * the GFNs. | ||
328 | * This parameter may be NULL if nr_frames is 0. | ||
329 | */ | ||
330 | GUEST_HANDLE(xen_pfn_t) frame_list; | ||
331 | }; | ||
332 | DEFINE_GUEST_HANDLE_STRUCT(xen_mem_acquire_resource); | ||
333 | |||
268 | #endif /* __XEN_PUBLIC_MEMORY_H__ */ | 334 | #endif /* __XEN_PUBLIC_MEMORY_H__ */ |
diff --git a/include/xen/interface/xen.h b/include/xen/interface/xen.h index 4f4830ef8f93..8bfb242f433e 100644 --- a/include/xen/interface/xen.h +++ b/include/xen/interface/xen.h | |||
@@ -265,9 +265,10 @@ | |||
265 | * | 265 | * |
266 | * PAT (bit 7 on) --> PWT (bit 3 on) and clear bit 7. | 266 | * PAT (bit 7 on) --> PWT (bit 3 on) and clear bit 7. |
267 | */ | 267 | */ |
268 | #define MMU_NORMAL_PT_UPDATE 0 /* checked '*ptr = val'. ptr is MA. */ | 268 | #define MMU_NORMAL_PT_UPDATE 0 /* checked '*ptr = val'. ptr is MA. */ |
269 | #define MMU_MACHPHYS_UPDATE 1 /* ptr = MA of frame to modify entry for */ | 269 | #define MMU_MACHPHYS_UPDATE 1 /* ptr = MA of frame to modify entry for */ |
270 | #define MMU_PT_UPDATE_PRESERVE_AD 2 /* atomically: *ptr = val | (*ptr&(A|D)) */ | 270 | #define MMU_PT_UPDATE_PRESERVE_AD 2 /* atomically: *ptr = val | (*ptr&(A|D)) */ |
271 | #define MMU_PT_UPDATE_NO_TRANSLATE 3 /* checked '*ptr = val'. ptr is MA. */ | ||
271 | 272 | ||
272 | /* | 273 | /* |
273 | * MMU EXTENDED OPERATIONS | 274 | * MMU EXTENDED OPERATIONS |
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h index fd23e42c6024..fd18c974a619 100644 --- a/include/xen/xen-ops.h +++ b/include/xen/xen-ops.h | |||
@@ -63,7 +63,7 @@ static inline void xen_destroy_contiguous_region(phys_addr_t pstart, | |||
63 | struct vm_area_struct; | 63 | struct vm_area_struct; |
64 | 64 | ||
65 | /* | 65 | /* |
66 | * xen_remap_domain_gfn_array() - map an array of foreign frames | 66 | * xen_remap_domain_gfn_array() - map an array of foreign frames by gfn |
67 | * @vma: VMA to map the pages into | 67 | * @vma: VMA to map the pages into |
68 | * @addr: Address at which to map the pages | 68 | * @addr: Address at which to map the pages |
69 | * @gfn: Array of GFNs to map | 69 | * @gfn: Array of GFNs to map |
@@ -86,6 +86,28 @@ int xen_remap_domain_gfn_array(struct vm_area_struct *vma, | |||
86 | unsigned domid, | 86 | unsigned domid, |
87 | struct page **pages); | 87 | struct page **pages); |
88 | 88 | ||
89 | /* | ||
90 | * xen_remap_domain_mfn_array() - map an array of foreign frames by mfn | ||
91 | * @vma: VMA to map the pages into | ||
92 | * @addr: Address at which to map the pages | ||
93 | * @mfn: Array of MFNs to map | ||
94 | * @nr: Number entries in the MFN array | ||
95 | * @err_ptr: Returns per-MFN error status. | ||
96 | * @prot: page protection mask | ||
97 | * @domid: Domain owning the pages | ||
98 | * @pages: Array of pages if this domain has an auto-translated physmap | ||
99 | * | ||
100 | * @mfn and @err_ptr may point to the same buffer, the MFNs will be | ||
101 | * overwritten by the error codes after they are mapped. | ||
102 | * | ||
103 | * Returns the number of successfully mapped frames, or a -ve error | ||
104 | * code. | ||
105 | */ | ||
106 | int xen_remap_domain_mfn_array(struct vm_area_struct *vma, | ||
107 | unsigned long addr, xen_pfn_t *mfn, int nr, | ||
108 | int *err_ptr, pgprot_t prot, | ||
109 | unsigned int domid, struct page **pages); | ||
110 | |||
89 | /* xen_remap_domain_gfn_range() - map a range of foreign frames | 111 | /* xen_remap_domain_gfn_range() - map a range of foreign frames |
90 | * @vma: VMA to map the pages into | 112 | * @vma: VMA to map the pages into |
91 | * @addr: Address at which to map the pages | 113 | * @addr: Address at which to map the pages |