aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/xen
diff options
context:
space:
mode:
authorIan Campbell <ian.campbell@citrix.com>2012-10-03 11:37:09 -0400
committerIan Campbell <ian.campbell@citrix.com>2012-11-29 09:00:19 -0500
commitf832da068b0aadb15f747f6427b6bf945f525ba4 (patch)
tree51e8c8e52d49f0e3754b93d862d161be55ae15df /arch/arm/xen
parent7892f6928d0cd9ef9200a193183c2033b3143dab (diff)
xen: arm: implement remap interfaces needed for privcmd mappings.
We use XENMEM_add_to_physmap_range which is the preferred interface for foreign mappings. Acked-by: Mukesh Rathor <mukesh.rathor@oracle.com> Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'arch/arm/xen')
-rw-r--r--arch/arm/xen/enlighten.c100
1 files changed, 97 insertions, 3 deletions
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
index ba5cc134a7d3..f28fc1ac8760 100644
--- a/arch/arm/xen/enlighten.c
+++ b/arch/arm/xen/enlighten.c
@@ -9,6 +9,7 @@
9#include <xen/platform_pci.h> 9#include <xen/platform_pci.h>
10#include <xen/xenbus.h> 10#include <xen/xenbus.h>
11#include <xen/page.h> 11#include <xen/page.h>
12#include <xen/xen-ops.h>
12#include <asm/xen/hypervisor.h> 13#include <asm/xen/hypervisor.h>
13#include <asm/xen/hypercall.h> 14#include <asm/xen/hypercall.h>
14#include <linux/interrupt.h> 15#include <linux/interrupt.h>
@@ -18,6 +19,8 @@
18#include <linux/of_irq.h> 19#include <linux/of_irq.h>
19#include <linux/of_address.h> 20#include <linux/of_address.h>
20 21
22#include <linux/mm.h>
23
21struct start_info _xen_start_info; 24struct start_info _xen_start_info;
22struct start_info *xen_start_info = &_xen_start_info; 25struct start_info *xen_start_info = &_xen_start_info;
23EXPORT_SYMBOL_GPL(xen_start_info); 26EXPORT_SYMBOL_GPL(xen_start_info);
@@ -43,15 +46,106 @@ EXPORT_SYMBOL_GPL(xen_platform_pci_unplug);
43 46
44static __read_mostly int xen_events_irq = -1; 47static __read_mostly int xen_events_irq = -1;
45 48
49/* map fgmfn of domid to lpfn in the current domain */
50static int map_foreign_page(unsigned long lpfn, unsigned long fgmfn,
51 unsigned int domid)
52{
53 int rc;
54 struct xen_add_to_physmap_range xatp = {
55 .domid = DOMID_SELF,
56 .foreign_domid = domid,
57 .size = 1,
58 .space = XENMAPSPACE_gmfn_foreign,
59 };
60 xen_ulong_t idx = fgmfn;
61 xen_pfn_t gpfn = lpfn;
62
63 set_xen_guest_handle(xatp.idxs, &idx);
64 set_xen_guest_handle(xatp.gpfns, &gpfn);
65
66 rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap_range, &xatp);
67 if (rc) {
68 pr_warn("Failed to map pfn to mfn rc:%d pfn:%lx mfn:%lx\n",
69 rc, lpfn, fgmfn);
70 return 1;
71 }
72 return 0;
73}
74
75struct remap_data {
76 xen_pfn_t fgmfn; /* foreign domain's gmfn */
77 pgprot_t prot;
78 domid_t domid;
79 struct vm_area_struct *vma;
80 int index;
81 struct page **pages;
82 struct xen_remap_mfn_info *info;
83};
84
85static int remap_pte_fn(pte_t *ptep, pgtable_t token, unsigned long addr,
86 void *data)
87{
88 struct remap_data *info = data;
89 struct page *page = info->pages[info->index++];
90 unsigned long pfn = page_to_pfn(page);
91 pte_t pte = pfn_pte(pfn, info->prot);
92
93 if (map_foreign_page(pfn, info->fgmfn, info->domid))
94 return -EFAULT;
95 set_pte_at(info->vma->vm_mm, addr, ptep, pte);
96
97 return 0;
98}
99
46int xen_remap_domain_mfn_range(struct vm_area_struct *vma, 100int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
47 unsigned long addr, 101 unsigned long addr,
48 unsigned long mfn, int nr, 102 xen_pfn_t mfn, int nr,
49 pgprot_t prot, unsigned domid) 103 pgprot_t prot, unsigned domid,
104 struct page **pages)
50{ 105{
51 return -ENOSYS; 106 int err;
107 struct remap_data data;
108
109 /* TBD: Batching, current sole caller only does page at a time */
110 if (nr > 1)
111 return -EINVAL;
112
113 data.fgmfn = mfn;
114 data.prot = prot;
115 data.domid = domid;
116 data.vma = vma;
117 data.index = 0;
118 data.pages = pages;
119 err = apply_to_page_range(vma->vm_mm, addr, nr << PAGE_SHIFT,
120 remap_pte_fn, &data);
121 return err;
52} 122}
53EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range); 123EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range);
54 124
125int xen_unmap_domain_mfn_range(struct vm_area_struct *vma,
126 int nr, struct page **pages)
127{
128 int i;
129
130 for (i = 0; i < nr; i++) {
131 struct xen_remove_from_physmap xrp;
132 unsigned long rc, pfn;
133
134 pfn = page_to_pfn(pages[i]);
135
136 xrp.domid = DOMID_SELF;
137 xrp.gpfn = pfn;
138 rc = HYPERVISOR_memory_op(XENMEM_remove_from_physmap, &xrp);
139 if (rc) {
140 pr_warn("Failed to unmap pfn:%lx rc:%ld\n",
141 pfn, rc);
142 return rc;
143 }
144 }
145 return 0;
146}
147EXPORT_SYMBOL_GPL(xen_unmap_domain_mfn_range);
148
55/* 149/*
56 * see Documentation/devicetree/bindings/arm/xen.txt for the 150 * see Documentation/devicetree/bindings/arm/xen.txt for the
57 * documentation of the Xen Device Tree format. 151 * documentation of the Xen Device Tree format.