diff options
-rw-r--r-- | arch/x86/xen/grant-table.c | 57 | ||||
-rw-r--r-- | drivers/xen/xlate_mmu.c | 61 | ||||
-rw-r--r-- | include/xen/xen-ops.h | 2 |
3 files changed, 69 insertions, 51 deletions
diff --git a/arch/x86/xen/grant-table.c b/arch/x86/xen/grant-table.c index e079500b17f3..de4144c24f1c 100644 --- a/arch/x86/xen/grant-table.c +++ b/arch/x86/xen/grant-table.c | |||
@@ -111,63 +111,18 @@ int arch_gnttab_init(unsigned long nr_shared) | |||
111 | } | 111 | } |
112 | 112 | ||
113 | #ifdef CONFIG_XEN_PVH | 113 | #ifdef CONFIG_XEN_PVH |
114 | #include <xen/balloon.h> | ||
115 | #include <xen/events.h> | 114 | #include <xen/events.h> |
116 | #include <linux/slab.h> | 115 | #include <xen/xen-ops.h> |
117 | static int __init xlated_setup_gnttab_pages(void) | ||
118 | { | ||
119 | struct page **pages; | ||
120 | xen_pfn_t *pfns; | ||
121 | void *vaddr; | ||
122 | int rc; | ||
123 | unsigned int i; | ||
124 | unsigned long nr_grant_frames = gnttab_max_grant_frames(); | ||
125 | |||
126 | BUG_ON(nr_grant_frames == 0); | ||
127 | pages = kcalloc(nr_grant_frames, sizeof(pages[0]), GFP_KERNEL); | ||
128 | if (!pages) | ||
129 | return -ENOMEM; | ||
130 | |||
131 | pfns = kcalloc(nr_grant_frames, sizeof(pfns[0]), GFP_KERNEL); | ||
132 | if (!pfns) { | ||
133 | kfree(pages); | ||
134 | return -ENOMEM; | ||
135 | } | ||
136 | rc = alloc_xenballooned_pages(nr_grant_frames, pages); | ||
137 | if (rc) { | ||
138 | pr_warn("%s Couldn't balloon alloc %ld pfns rc:%d\n", __func__, | ||
139 | nr_grant_frames, rc); | ||
140 | kfree(pages); | ||
141 | kfree(pfns); | ||
142 | return rc; | ||
143 | } | ||
144 | for (i = 0; i < nr_grant_frames; i++) | ||
145 | pfns[i] = page_to_pfn(pages[i]); | ||
146 | |||
147 | vaddr = vmap(pages, nr_grant_frames, 0, PAGE_KERNEL); | ||
148 | if (!vaddr) { | ||
149 | pr_warn("%s Couldn't map %ld pfns rc:%d\n", __func__, | ||
150 | nr_grant_frames, rc); | ||
151 | free_xenballooned_pages(nr_grant_frames, pages); | ||
152 | kfree(pages); | ||
153 | kfree(pfns); | ||
154 | return -ENOMEM; | ||
155 | } | ||
156 | kfree(pages); | ||
157 | |||
158 | xen_auto_xlat_grant_frames.pfn = pfns; | ||
159 | xen_auto_xlat_grant_frames.count = nr_grant_frames; | ||
160 | xen_auto_xlat_grant_frames.vaddr = vaddr; | ||
161 | |||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static int __init xen_pvh_gnttab_setup(void) | 116 | static int __init xen_pvh_gnttab_setup(void) |
166 | { | 117 | { |
167 | if (!xen_pvh_domain()) | 118 | if (!xen_pvh_domain()) |
168 | return -ENODEV; | 119 | return -ENODEV; |
169 | 120 | ||
170 | return xlated_setup_gnttab_pages(); | 121 | xen_auto_xlat_grant_frames.count = gnttab_max_grant_frames(); |
122 | |||
123 | return xen_xlate_map_ballooned_pages(&xen_auto_xlat_grant_frames.pfn, | ||
124 | &xen_auto_xlat_grant_frames.vaddr, | ||
125 | xen_auto_xlat_grant_frames.count); | ||
171 | } | 126 | } |
172 | /* Call it _before_ __gnttab_init as we need to initialize the | 127 | /* Call it _before_ __gnttab_init as we need to initialize the |
173 | * xen_auto_xlat_grant_frames first. */ | 128 | * xen_auto_xlat_grant_frames first. */ |
diff --git a/drivers/xen/xlate_mmu.c b/drivers/xen/xlate_mmu.c index 5063c5e796b7..9692656f2fdf 100644 --- a/drivers/xen/xlate_mmu.c +++ b/drivers/xen/xlate_mmu.c | |||
@@ -29,6 +29,8 @@ | |||
29 | */ | 29 | */ |
30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
31 | #include <linux/mm.h> | 31 | #include <linux/mm.h> |
32 | #include <linux/slab.h> | ||
33 | #include <linux/vmalloc.h> | ||
32 | 34 | ||
33 | #include <asm/xen/hypercall.h> | 35 | #include <asm/xen/hypercall.h> |
34 | #include <asm/xen/hypervisor.h> | 36 | #include <asm/xen/hypervisor.h> |
@@ -37,6 +39,7 @@ | |||
37 | #include <xen/page.h> | 39 | #include <xen/page.h> |
38 | #include <xen/interface/xen.h> | 40 | #include <xen/interface/xen.h> |
39 | #include <xen/interface/memory.h> | 41 | #include <xen/interface/memory.h> |
42 | #include <xen/balloon.h> | ||
40 | 43 | ||
41 | typedef void (*xen_gfn_fn_t)(unsigned long gfn, void *data); | 44 | typedef void (*xen_gfn_fn_t)(unsigned long gfn, void *data); |
42 | 45 | ||
@@ -185,3 +188,61 @@ int xen_xlate_unmap_gfn_range(struct vm_area_struct *vma, | |||
185 | return 0; | 188 | return 0; |
186 | } | 189 | } |
187 | EXPORT_SYMBOL_GPL(xen_xlate_unmap_gfn_range); | 190 | EXPORT_SYMBOL_GPL(xen_xlate_unmap_gfn_range); |
191 | |||
192 | /** | ||
193 | * xen_xlate_map_ballooned_pages - map a new set of ballooned pages | ||
194 | * @gfns: returns the array of corresponding GFNs | ||
195 | * @virt: returns the virtual address of the mapped region | ||
196 | * @nr_grant_frames: number of GFNs | ||
197 | * @return 0 on success, error otherwise | ||
198 | * | ||
199 | * This allocates a set of ballooned pages and maps them into the | ||
200 | * kernel's address space. | ||
201 | */ | ||
202 | int __init xen_xlate_map_ballooned_pages(xen_pfn_t **gfns, void **virt, | ||
203 | unsigned long nr_grant_frames) | ||
204 | { | ||
205 | struct page **pages; | ||
206 | xen_pfn_t *pfns; | ||
207 | void *vaddr; | ||
208 | int rc; | ||
209 | unsigned int i; | ||
210 | |||
211 | BUG_ON(nr_grant_frames == 0); | ||
212 | pages = kcalloc(nr_grant_frames, sizeof(pages[0]), GFP_KERNEL); | ||
213 | if (!pages) | ||
214 | return -ENOMEM; | ||
215 | |||
216 | pfns = kcalloc(nr_grant_frames, sizeof(pfns[0]), GFP_KERNEL); | ||
217 | if (!pfns) { | ||
218 | kfree(pages); | ||
219 | return -ENOMEM; | ||
220 | } | ||
221 | rc = alloc_xenballooned_pages(nr_grant_frames, pages); | ||
222 | if (rc) { | ||
223 | pr_warn("%s Couldn't balloon alloc %ld pfns rc:%d\n", __func__, | ||
224 | nr_grant_frames, rc); | ||
225 | kfree(pages); | ||
226 | kfree(pfns); | ||
227 | return rc; | ||
228 | } | ||
229 | for (i = 0; i < nr_grant_frames; i++) | ||
230 | pfns[i] = page_to_pfn(pages[i]); | ||
231 | |||
232 | vaddr = vmap(pages, nr_grant_frames, 0, PAGE_KERNEL); | ||
233 | if (!vaddr) { | ||
234 | pr_warn("%s Couldn't map %ld pfns rc:%d\n", __func__, | ||
235 | nr_grant_frames, rc); | ||
236 | free_xenballooned_pages(nr_grant_frames, pages); | ||
237 | kfree(pages); | ||
238 | kfree(pfns); | ||
239 | return -ENOMEM; | ||
240 | } | ||
241 | kfree(pages); | ||
242 | |||
243 | *gfns = pfns; | ||
244 | *virt = vaddr; | ||
245 | |||
246 | return 0; | ||
247 | } | ||
248 | EXPORT_SYMBOL_GPL(xen_xlate_map_ballooned_pages); | ||
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h index 86abe07b20ec..072be1c29917 100644 --- a/include/xen/xen-ops.h +++ b/include/xen/xen-ops.h | |||
@@ -85,6 +85,8 @@ int xen_xlate_remap_gfn_array(struct vm_area_struct *vma, | |||
85 | struct page **pages); | 85 | struct page **pages); |
86 | int xen_xlate_unmap_gfn_range(struct vm_area_struct *vma, | 86 | int xen_xlate_unmap_gfn_range(struct vm_area_struct *vma, |
87 | int nr, struct page **pages); | 87 | int nr, struct page **pages); |
88 | int xen_xlate_map_ballooned_pages(xen_pfn_t **pfns, void **vaddr, | ||
89 | unsigned long nr_grant_frames); | ||
88 | 90 | ||
89 | bool xen_running_on_version_or_later(unsigned int major, unsigned int minor); | 91 | bool xen_running_on_version_or_later(unsigned int major, unsigned int minor); |
90 | 92 | ||