aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-01-13 21:46:48 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-13 21:46:48 -0500
commit9c4bc1c2befbbdce4b9fd526e67a7a2ea143ffa2 (patch)
tree1b08c1bb00ce477ca947461777cd7e24de72c148
parent2c0076d8c7eb1dafa03d0a792444862080b34106 (diff)
parente1b478e4ec4477520767d1a920433626263a2a6b (diff)
Merge branch 'stable/gntdev' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen
* 'stable/gntdev' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen: xen/p2m: Fix module linking error. xen p2m: clear the old pte when adding a page to m2p_override xen gntdev: use gnttab_map_refs and gnttab_unmap_refs xen: introduce gnttab_map_refs and gnttab_unmap_refs xen p2m: transparently change the p2m mappings in the m2p override xen/gntdev: Fix circular locking dependency xen/gntdev: stop using "token" argument xen: gntdev: move use of GNTMAP_contains_pte next to the map_op xen: add m2p override mechanism xen: move p2m handling to separate file xen/gntdev: add VM_PFNMAP to vma xen/gntdev: allow usermode to map granted pages xen: define gnttab_set_map_op/unmap_op Fix up trivial conflict in drivers/xen/Kconfig
-rw-r--r--arch/x86/include/asm/xen/page.h16
-rw-r--r--arch/x86/xen/Makefile3
-rw-r--r--arch/x86/xen/mmu.c365
-rw-r--r--arch/x86/xen/p2m.c510
-rw-r--r--drivers/xen/Kconfig9
-rw-r--r--drivers/xen/Makefile2
-rw-r--r--drivers/xen/gntdev.c665
-rw-r--r--drivers/xen/grant-table.c46
-rw-r--r--include/xen/gntdev.h119
-rw-r--r--include/xen/grant_table.h44
10 files changed, 1408 insertions, 371 deletions
diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h
index 8760cc60a21c..f25bdf238a33 100644
--- a/arch/x86/include/asm/xen/page.h
+++ b/arch/x86/include/asm/xen/page.h
@@ -42,6 +42,11 @@ extern unsigned int machine_to_phys_order;
42extern unsigned long get_phys_to_machine(unsigned long pfn); 42extern unsigned long get_phys_to_machine(unsigned long pfn);
43extern bool set_phys_to_machine(unsigned long pfn, unsigned long mfn); 43extern bool set_phys_to_machine(unsigned long pfn, unsigned long mfn);
44 44
45extern int m2p_add_override(unsigned long mfn, struct page *page);
46extern int m2p_remove_override(struct page *page);
47extern struct page *m2p_find_override(unsigned long mfn);
48extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn);
49
45static inline unsigned long pfn_to_mfn(unsigned long pfn) 50static inline unsigned long pfn_to_mfn(unsigned long pfn)
46{ 51{
47 unsigned long mfn; 52 unsigned long mfn;
@@ -72,9 +77,6 @@ static inline unsigned long mfn_to_pfn(unsigned long mfn)
72 if (xen_feature(XENFEAT_auto_translated_physmap)) 77 if (xen_feature(XENFEAT_auto_translated_physmap))
73 return mfn; 78 return mfn;
74 79
75 if (unlikely((mfn >> machine_to_phys_order) != 0))
76 return ~0;
77
78 pfn = 0; 80 pfn = 0;
79 /* 81 /*
80 * The array access can fail (e.g., device space beyond end of RAM). 82 * The array access can fail (e.g., device space beyond end of RAM).
@@ -83,6 +85,14 @@ static inline unsigned long mfn_to_pfn(unsigned long mfn)
83 */ 85 */
84 __get_user(pfn, &machine_to_phys_mapping[mfn]); 86 __get_user(pfn, &machine_to_phys_mapping[mfn]);
85 87
88 /*
89 * If this appears to be a foreign mfn (because the pfn
90 * doesn't map back to the mfn), then check the local override
91 * table to see if there's a better pfn to use.
92 */
93 if (get_phys_to_machine(pfn) != mfn)
94 pfn = m2p_find_override_pfn(mfn, pfn);
95
86 return pfn; 96 return pfn;
87} 97}
88 98
diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile
index 779385158915..17c565de3d64 100644
--- a/arch/x86/xen/Makefile
+++ b/arch/x86/xen/Makefile
@@ -12,7 +12,8 @@ CFLAGS_mmu.o := $(nostackp)
12 12
13obj-y := enlighten.o setup.o multicalls.o mmu.o irq.o \ 13obj-y := enlighten.o setup.o multicalls.o mmu.o irq.o \
14 time.o xen-asm.o xen-asm_$(BITS).o \ 14 time.o xen-asm.o xen-asm_$(BITS).o \
15 grant-table.o suspend.o platform-pci-unplug.o 15 grant-table.o suspend.o platform-pci-unplug.o \
16 p2m.o
16 17
17obj-$(CONFIG_SMP) += smp.o 18obj-$(CONFIG_SMP) += smp.o
18obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o 19obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 44924e551fde..7575e55cd52e 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -173,371 +173,6 @@ DEFINE_PER_CPU(unsigned long, xen_current_cr3); /* actual vcpu cr3 */
173 */ 173 */
174#define USER_LIMIT ((STACK_TOP_MAX + PGDIR_SIZE - 1) & PGDIR_MASK) 174#define USER_LIMIT ((STACK_TOP_MAX + PGDIR_SIZE - 1) & PGDIR_MASK)
175 175
176/*
177 * Xen leaves the responsibility for maintaining p2m mappings to the
178 * guests themselves, but it must also access and update the p2m array
179 * during suspend/resume when all the pages are reallocated.
180 *
181 * The p2m table is logically a flat array, but we implement it as a
182 * three-level tree to allow the address space to be sparse.
183 *
184 * Xen
185 * |
186 * p2m_top p2m_top_mfn
187 * / \ / \
188 * p2m_mid p2m_mid p2m_mid_mfn p2m_mid_mfn
189 * / \ / \ / /
190 * p2m p2m p2m p2m p2m p2m p2m ...
191 *
192 * The p2m_mid_mfn pages are mapped by p2m_top_mfn_p.
193 *
194 * The p2m_top and p2m_top_mfn levels are limited to 1 page, so the
195 * maximum representable pseudo-physical address space is:
196 * P2M_TOP_PER_PAGE * P2M_MID_PER_PAGE * P2M_PER_PAGE pages
197 *
198 * P2M_PER_PAGE depends on the architecture, as a mfn is always
199 * unsigned long (8 bytes on 64-bit, 4 bytes on 32), leading to
200 * 512 and 1024 entries respectively.
201 */
202
203unsigned long xen_max_p2m_pfn __read_mostly;
204
205#define P2M_PER_PAGE (PAGE_SIZE / sizeof(unsigned long))
206#define P2M_MID_PER_PAGE (PAGE_SIZE / sizeof(unsigned long *))
207#define P2M_TOP_PER_PAGE (PAGE_SIZE / sizeof(unsigned long **))
208
209#define MAX_P2M_PFN (P2M_TOP_PER_PAGE * P2M_MID_PER_PAGE * P2M_PER_PAGE)
210
211/* Placeholders for holes in the address space */
212static RESERVE_BRK_ARRAY(unsigned long, p2m_missing, P2M_PER_PAGE);
213static RESERVE_BRK_ARRAY(unsigned long *, p2m_mid_missing, P2M_MID_PER_PAGE);
214static RESERVE_BRK_ARRAY(unsigned long, p2m_mid_missing_mfn, P2M_MID_PER_PAGE);
215
216static RESERVE_BRK_ARRAY(unsigned long **, p2m_top, P2M_TOP_PER_PAGE);
217static RESERVE_BRK_ARRAY(unsigned long, p2m_top_mfn, P2M_TOP_PER_PAGE);
218static RESERVE_BRK_ARRAY(unsigned long *, p2m_top_mfn_p, P2M_TOP_PER_PAGE);
219
220RESERVE_BRK(p2m_mid, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
221RESERVE_BRK(p2m_mid_mfn, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
222
223static inline unsigned p2m_top_index(unsigned long pfn)
224{
225 BUG_ON(pfn >= MAX_P2M_PFN);
226 return pfn / (P2M_MID_PER_PAGE * P2M_PER_PAGE);
227}
228
229static inline unsigned p2m_mid_index(unsigned long pfn)
230{
231 return (pfn / P2M_PER_PAGE) % P2M_MID_PER_PAGE;
232}
233
234static inline unsigned p2m_index(unsigned long pfn)
235{
236 return pfn % P2M_PER_PAGE;
237}
238
239static void p2m_top_init(unsigned long ***top)
240{
241 unsigned i;
242
243 for (i = 0; i < P2M_TOP_PER_PAGE; i++)
244 top[i] = p2m_mid_missing;
245}
246
247static void p2m_top_mfn_init(unsigned long *top)
248{
249 unsigned i;
250
251 for (i = 0; i < P2M_TOP_PER_PAGE; i++)
252 top[i] = virt_to_mfn(p2m_mid_missing_mfn);
253}
254
255static void p2m_top_mfn_p_init(unsigned long **top)
256{
257 unsigned i;
258
259 for (i = 0; i < P2M_TOP_PER_PAGE; i++)
260 top[i] = p2m_mid_missing_mfn;
261}
262
263static void p2m_mid_init(unsigned long **mid)
264{
265 unsigned i;
266
267 for (i = 0; i < P2M_MID_PER_PAGE; i++)
268 mid[i] = p2m_missing;
269}
270
271static void p2m_mid_mfn_init(unsigned long *mid)
272{
273 unsigned i;
274
275 for (i = 0; i < P2M_MID_PER_PAGE; i++)
276 mid[i] = virt_to_mfn(p2m_missing);
277}
278
279static void p2m_init(unsigned long *p2m)
280{
281 unsigned i;
282
283 for (i = 0; i < P2M_MID_PER_PAGE; i++)
284 p2m[i] = INVALID_P2M_ENTRY;
285}
286
287/*
288 * Build the parallel p2m_top_mfn and p2m_mid_mfn structures
289 *
290 * This is called both at boot time, and after resuming from suspend:
291 * - At boot time we're called very early, and must use extend_brk()
292 * to allocate memory.
293 *
294 * - After resume we're called from within stop_machine, but the mfn
295 * tree should alreay be completely allocated.
296 */
297void xen_build_mfn_list_list(void)
298{
299 unsigned long pfn;
300
301 /* Pre-initialize p2m_top_mfn to be completely missing */
302 if (p2m_top_mfn == NULL) {
303 p2m_mid_missing_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
304 p2m_mid_mfn_init(p2m_mid_missing_mfn);
305
306 p2m_top_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
307 p2m_top_mfn_p_init(p2m_top_mfn_p);
308
309 p2m_top_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
310 p2m_top_mfn_init(p2m_top_mfn);
311 } else {
312 /* Reinitialise, mfn's all change after migration */
313 p2m_mid_mfn_init(p2m_mid_missing_mfn);
314 }
315
316 for (pfn = 0; pfn < xen_max_p2m_pfn; pfn += P2M_PER_PAGE) {
317 unsigned topidx = p2m_top_index(pfn);
318 unsigned mididx = p2m_mid_index(pfn);
319 unsigned long **mid;
320 unsigned long *mid_mfn_p;
321
322 mid = p2m_top[topidx];
323 mid_mfn_p = p2m_top_mfn_p[topidx];
324
325 /* Don't bother allocating any mfn mid levels if
326 * they're just missing, just update the stored mfn,
327 * since all could have changed over a migrate.
328 */
329 if (mid == p2m_mid_missing) {
330 BUG_ON(mididx);
331 BUG_ON(mid_mfn_p != p2m_mid_missing_mfn);
332 p2m_top_mfn[topidx] = virt_to_mfn(p2m_mid_missing_mfn);
333 pfn += (P2M_MID_PER_PAGE - 1) * P2M_PER_PAGE;
334 continue;
335 }
336
337 if (mid_mfn_p == p2m_mid_missing_mfn) {
338 /*
339 * XXX boot-time only! We should never find
340 * missing parts of the mfn tree after
341 * runtime. extend_brk() will BUG if we call
342 * it too late.
343 */
344 mid_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
345 p2m_mid_mfn_init(mid_mfn_p);
346
347 p2m_top_mfn_p[topidx] = mid_mfn_p;
348 }
349
350 p2m_top_mfn[topidx] = virt_to_mfn(mid_mfn_p);
351 mid_mfn_p[mididx] = virt_to_mfn(mid[mididx]);
352 }
353}
354
355void xen_setup_mfn_list_list(void)
356{
357 BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info);
358
359 HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
360 virt_to_mfn(p2m_top_mfn);
361 HYPERVISOR_shared_info->arch.max_pfn = xen_max_p2m_pfn;
362}
363
364/* Set up p2m_top to point to the domain-builder provided p2m pages */
365void __init xen_build_dynamic_phys_to_machine(void)
366{
367 unsigned long *mfn_list = (unsigned long *)xen_start_info->mfn_list;
368 unsigned long max_pfn = min(MAX_DOMAIN_PAGES, xen_start_info->nr_pages);
369 unsigned long pfn;
370
371 xen_max_p2m_pfn = max_pfn;
372
373 p2m_missing = extend_brk(PAGE_SIZE, PAGE_SIZE);
374 p2m_init(p2m_missing);
375
376 p2m_mid_missing = extend_brk(PAGE_SIZE, PAGE_SIZE);
377 p2m_mid_init(p2m_mid_missing);
378
379 p2m_top = extend_brk(PAGE_SIZE, PAGE_SIZE);
380 p2m_top_init(p2m_top);
381
382 /*
383 * The domain builder gives us a pre-constructed p2m array in
384 * mfn_list for all the pages initially given to us, so we just
385 * need to graft that into our tree structure.
386 */
387 for (pfn = 0; pfn < max_pfn; pfn += P2M_PER_PAGE) {
388 unsigned topidx = p2m_top_index(pfn);
389 unsigned mididx = p2m_mid_index(pfn);
390
391 if (p2m_top[topidx] == p2m_mid_missing) {
392 unsigned long **mid = extend_brk(PAGE_SIZE, PAGE_SIZE);
393 p2m_mid_init(mid);
394
395 p2m_top[topidx] = mid;
396 }
397
398 p2m_top[topidx][mididx] = &mfn_list[pfn];
399 }
400}
401
402unsigned long get_phys_to_machine(unsigned long pfn)
403{
404 unsigned topidx, mididx, idx;
405
406 if (unlikely(pfn >= MAX_P2M_PFN))
407 return INVALID_P2M_ENTRY;
408
409 topidx = p2m_top_index(pfn);
410 mididx = p2m_mid_index(pfn);
411 idx = p2m_index(pfn);
412
413 return p2m_top[topidx][mididx][idx];
414}
415EXPORT_SYMBOL_GPL(get_phys_to_machine);
416
417static void *alloc_p2m_page(void)
418{
419 return (void *)__get_free_page(GFP_KERNEL | __GFP_REPEAT);
420}
421
422static void free_p2m_page(void *p)
423{
424 free_page((unsigned long)p);
425}
426
427/*
428 * Fully allocate the p2m structure for a given pfn. We need to check
429 * that both the top and mid levels are allocated, and make sure the
430 * parallel mfn tree is kept in sync. We may race with other cpus, so
431 * the new pages are installed with cmpxchg; if we lose the race then
432 * simply free the page we allocated and use the one that's there.
433 */
434static bool alloc_p2m(unsigned long pfn)
435{
436 unsigned topidx, mididx;
437 unsigned long ***top_p, **mid;
438 unsigned long *top_mfn_p, *mid_mfn;
439
440 topidx = p2m_top_index(pfn);
441 mididx = p2m_mid_index(pfn);
442
443 top_p = &p2m_top[topidx];
444 mid = *top_p;
445
446 if (mid == p2m_mid_missing) {
447 /* Mid level is missing, allocate a new one */
448 mid = alloc_p2m_page();
449 if (!mid)
450 return false;
451
452 p2m_mid_init(mid);
453
454 if (cmpxchg(top_p, p2m_mid_missing, mid) != p2m_mid_missing)
455 free_p2m_page(mid);
456 }
457
458 top_mfn_p = &p2m_top_mfn[topidx];
459 mid_mfn = p2m_top_mfn_p[topidx];
460
461 BUG_ON(virt_to_mfn(mid_mfn) != *top_mfn_p);
462
463 if (mid_mfn == p2m_mid_missing_mfn) {
464 /* Separately check the mid mfn level */
465 unsigned long missing_mfn;
466 unsigned long mid_mfn_mfn;
467
468 mid_mfn = alloc_p2m_page();
469 if (!mid_mfn)
470 return false;
471
472 p2m_mid_mfn_init(mid_mfn);
473
474 missing_mfn = virt_to_mfn(p2m_mid_missing_mfn);
475 mid_mfn_mfn = virt_to_mfn(mid_mfn);
476 if (cmpxchg(top_mfn_p, missing_mfn, mid_mfn_mfn) != missing_mfn)
477 free_p2m_page(mid_mfn);
478 else
479 p2m_top_mfn_p[topidx] = mid_mfn;
480 }
481
482 if (p2m_top[topidx][mididx] == p2m_missing) {
483 /* p2m leaf page is missing */
484 unsigned long *p2m;
485
486 p2m = alloc_p2m_page();
487 if (!p2m)
488 return false;
489
490 p2m_init(p2m);
491
492 if (cmpxchg(&mid[mididx], p2m_missing, p2m) != p2m_missing)
493 free_p2m_page(p2m);
494 else
495 mid_mfn[mididx] = virt_to_mfn(p2m);
496 }
497
498 return true;
499}
500
501/* Try to install p2m mapping; fail if intermediate bits missing */
502bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
503{
504 unsigned topidx, mididx, idx;
505
506 if (unlikely(pfn >= MAX_P2M_PFN)) {
507 BUG_ON(mfn != INVALID_P2M_ENTRY);
508 return true;
509 }
510
511 topidx = p2m_top_index(pfn);
512 mididx = p2m_mid_index(pfn);
513 idx = p2m_index(pfn);
514
515 if (p2m_top[topidx][mididx] == p2m_missing)
516 return mfn == INVALID_P2M_ENTRY;
517
518 p2m_top[topidx][mididx][idx] = mfn;
519
520 return true;
521}
522
523bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
524{
525 if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) {
526 BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
527 return true;
528 }
529
530 if (unlikely(!__set_phys_to_machine(pfn, mfn))) {
531 if (!alloc_p2m(pfn))
532 return false;
533
534 if (!__set_phys_to_machine(pfn, mfn))
535 return false;
536 }
537
538 return true;
539}
540
541unsigned long arbitrary_virt_to_mfn(void *vaddr) 176unsigned long arbitrary_virt_to_mfn(void *vaddr)
542{ 177{
543 xmaddr_t maddr = arbitrary_virt_to_machine(vaddr); 178 xmaddr_t maddr = arbitrary_virt_to_machine(vaddr);
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c
new file mode 100644
index 000000000000..8f2251d2a3f8
--- /dev/null
+++ b/arch/x86/xen/p2m.c
@@ -0,0 +1,510 @@
1/*
2 * Xen leaves the responsibility for maintaining p2m mappings to the
3 * guests themselves, but it must also access and update the p2m array
4 * during suspend/resume when all the pages are reallocated.
5 *
6 * The p2m table is logically a flat array, but we implement it as a
7 * three-level tree to allow the address space to be sparse.
8 *
9 * Xen
10 * |
11 * p2m_top p2m_top_mfn
12 * / \ / \
13 * p2m_mid p2m_mid p2m_mid_mfn p2m_mid_mfn
14 * / \ / \ / /
15 * p2m p2m p2m p2m p2m p2m p2m ...
16 *
17 * The p2m_mid_mfn pages are mapped by p2m_top_mfn_p.
18 *
19 * The p2m_top and p2m_top_mfn levels are limited to 1 page, so the
20 * maximum representable pseudo-physical address space is:
21 * P2M_TOP_PER_PAGE * P2M_MID_PER_PAGE * P2M_PER_PAGE pages
22 *
23 * P2M_PER_PAGE depends on the architecture, as a mfn is always
24 * unsigned long (8 bytes on 64-bit, 4 bytes on 32), leading to
25 * 512 and 1024 entries respectively.
26 */
27
28#include <linux/init.h>
29#include <linux/module.h>
30#include <linux/list.h>
31#include <linux/hash.h>
32#include <linux/sched.h>
33
34#include <asm/cache.h>
35#include <asm/setup.h>
36
37#include <asm/xen/page.h>
38#include <asm/xen/hypercall.h>
39#include <asm/xen/hypervisor.h>
40
41#include "xen-ops.h"
42
43static void __init m2p_override_init(void);
44
45unsigned long xen_max_p2m_pfn __read_mostly;
46
47#define P2M_PER_PAGE (PAGE_SIZE / sizeof(unsigned long))
48#define P2M_MID_PER_PAGE (PAGE_SIZE / sizeof(unsigned long *))
49#define P2M_TOP_PER_PAGE (PAGE_SIZE / sizeof(unsigned long **))
50
51#define MAX_P2M_PFN (P2M_TOP_PER_PAGE * P2M_MID_PER_PAGE * P2M_PER_PAGE)
52
53/* Placeholders for holes in the address space */
54static RESERVE_BRK_ARRAY(unsigned long, p2m_missing, P2M_PER_PAGE);
55static RESERVE_BRK_ARRAY(unsigned long *, p2m_mid_missing, P2M_MID_PER_PAGE);
56static RESERVE_BRK_ARRAY(unsigned long, p2m_mid_missing_mfn, P2M_MID_PER_PAGE);
57
58static RESERVE_BRK_ARRAY(unsigned long **, p2m_top, P2M_TOP_PER_PAGE);
59static RESERVE_BRK_ARRAY(unsigned long, p2m_top_mfn, P2M_TOP_PER_PAGE);
60static RESERVE_BRK_ARRAY(unsigned long *, p2m_top_mfn_p, P2M_TOP_PER_PAGE);
61
62RESERVE_BRK(p2m_mid, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
63RESERVE_BRK(p2m_mid_mfn, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
64
65static inline unsigned p2m_top_index(unsigned long pfn)
66{
67 BUG_ON(pfn >= MAX_P2M_PFN);
68 return pfn / (P2M_MID_PER_PAGE * P2M_PER_PAGE);
69}
70
71static inline unsigned p2m_mid_index(unsigned long pfn)
72{
73 return (pfn / P2M_PER_PAGE) % P2M_MID_PER_PAGE;
74}
75
76static inline unsigned p2m_index(unsigned long pfn)
77{
78 return pfn % P2M_PER_PAGE;
79}
80
81static void p2m_top_init(unsigned long ***top)
82{
83 unsigned i;
84
85 for (i = 0; i < P2M_TOP_PER_PAGE; i++)
86 top[i] = p2m_mid_missing;
87}
88
89static void p2m_top_mfn_init(unsigned long *top)
90{
91 unsigned i;
92
93 for (i = 0; i < P2M_TOP_PER_PAGE; i++)
94 top[i] = virt_to_mfn(p2m_mid_missing_mfn);
95}
96
97static void p2m_top_mfn_p_init(unsigned long **top)
98{
99 unsigned i;
100
101 for (i = 0; i < P2M_TOP_PER_PAGE; i++)
102 top[i] = p2m_mid_missing_mfn;
103}
104
105static void p2m_mid_init(unsigned long **mid)
106{
107 unsigned i;
108
109 for (i = 0; i < P2M_MID_PER_PAGE; i++)
110 mid[i] = p2m_missing;
111}
112
113static void p2m_mid_mfn_init(unsigned long *mid)
114{
115 unsigned i;
116
117 for (i = 0; i < P2M_MID_PER_PAGE; i++)
118 mid[i] = virt_to_mfn(p2m_missing);
119}
120
121static void p2m_init(unsigned long *p2m)
122{
123 unsigned i;
124
125 for (i = 0; i < P2M_MID_PER_PAGE; i++)
126 p2m[i] = INVALID_P2M_ENTRY;
127}
128
129/*
130 * Build the parallel p2m_top_mfn and p2m_mid_mfn structures
131 *
132 * This is called both at boot time, and after resuming from suspend:
133 * - At boot time we're called very early, and must use extend_brk()
134 * to allocate memory.
135 *
136 * - After resume we're called from within stop_machine, but the mfn
137 * tree should alreay be completely allocated.
138 */
139void xen_build_mfn_list_list(void)
140{
141 unsigned long pfn;
142
143 /* Pre-initialize p2m_top_mfn to be completely missing */
144 if (p2m_top_mfn == NULL) {
145 p2m_mid_missing_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
146 p2m_mid_mfn_init(p2m_mid_missing_mfn);
147
148 p2m_top_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
149 p2m_top_mfn_p_init(p2m_top_mfn_p);
150
151 p2m_top_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
152 p2m_top_mfn_init(p2m_top_mfn);
153 } else {
154 /* Reinitialise, mfn's all change after migration */
155 p2m_mid_mfn_init(p2m_mid_missing_mfn);
156 }
157
158 for (pfn = 0; pfn < xen_max_p2m_pfn; pfn += P2M_PER_PAGE) {
159 unsigned topidx = p2m_top_index(pfn);
160 unsigned mididx = p2m_mid_index(pfn);
161 unsigned long **mid;
162 unsigned long *mid_mfn_p;
163
164 mid = p2m_top[topidx];
165 mid_mfn_p = p2m_top_mfn_p[topidx];
166
167 /* Don't bother allocating any mfn mid levels if
168 * they're just missing, just update the stored mfn,
169 * since all could have changed over a migrate.
170 */
171 if (mid == p2m_mid_missing) {
172 BUG_ON(mididx);
173 BUG_ON(mid_mfn_p != p2m_mid_missing_mfn);
174 p2m_top_mfn[topidx] = virt_to_mfn(p2m_mid_missing_mfn);
175 pfn += (P2M_MID_PER_PAGE - 1) * P2M_PER_PAGE;
176 continue;
177 }
178
179 if (mid_mfn_p == p2m_mid_missing_mfn) {
180 /*
181 * XXX boot-time only! We should never find
182 * missing parts of the mfn tree after
183 * runtime. extend_brk() will BUG if we call
184 * it too late.
185 */
186 mid_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
187 p2m_mid_mfn_init(mid_mfn_p);
188
189 p2m_top_mfn_p[topidx] = mid_mfn_p;
190 }
191
192 p2m_top_mfn[topidx] = virt_to_mfn(mid_mfn_p);
193 mid_mfn_p[mididx] = virt_to_mfn(mid[mididx]);
194 }
195}
196
197void xen_setup_mfn_list_list(void)
198{
199 BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info);
200
201 HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
202 virt_to_mfn(p2m_top_mfn);
203 HYPERVISOR_shared_info->arch.max_pfn = xen_max_p2m_pfn;
204}
205
206/* Set up p2m_top to point to the domain-builder provided p2m pages */
207void __init xen_build_dynamic_phys_to_machine(void)
208{
209 unsigned long *mfn_list = (unsigned long *)xen_start_info->mfn_list;
210 unsigned long max_pfn = min(MAX_DOMAIN_PAGES, xen_start_info->nr_pages);
211 unsigned long pfn;
212
213 xen_max_p2m_pfn = max_pfn;
214
215 p2m_missing = extend_brk(PAGE_SIZE, PAGE_SIZE);
216 p2m_init(p2m_missing);
217
218 p2m_mid_missing = extend_brk(PAGE_SIZE, PAGE_SIZE);
219 p2m_mid_init(p2m_mid_missing);
220
221 p2m_top = extend_brk(PAGE_SIZE, PAGE_SIZE);
222 p2m_top_init(p2m_top);
223
224 /*
225 * The domain builder gives us a pre-constructed p2m array in
226 * mfn_list for all the pages initially given to us, so we just
227 * need to graft that into our tree structure.
228 */
229 for (pfn = 0; pfn < max_pfn; pfn += P2M_PER_PAGE) {
230 unsigned topidx = p2m_top_index(pfn);
231 unsigned mididx = p2m_mid_index(pfn);
232
233 if (p2m_top[topidx] == p2m_mid_missing) {
234 unsigned long **mid = extend_brk(PAGE_SIZE, PAGE_SIZE);
235 p2m_mid_init(mid);
236
237 p2m_top[topidx] = mid;
238 }
239
240 p2m_top[topidx][mididx] = &mfn_list[pfn];
241 }
242
243 m2p_override_init();
244}
245
246unsigned long get_phys_to_machine(unsigned long pfn)
247{
248 unsigned topidx, mididx, idx;
249
250 if (unlikely(pfn >= MAX_P2M_PFN))
251 return INVALID_P2M_ENTRY;
252
253 topidx = p2m_top_index(pfn);
254 mididx = p2m_mid_index(pfn);
255 idx = p2m_index(pfn);
256
257 return p2m_top[topidx][mididx][idx];
258}
259EXPORT_SYMBOL_GPL(get_phys_to_machine);
260
261static void *alloc_p2m_page(void)
262{
263 return (void *)__get_free_page(GFP_KERNEL | __GFP_REPEAT);
264}
265
266static void free_p2m_page(void *p)
267{
268 free_page((unsigned long)p);
269}
270
271/*
272 * Fully allocate the p2m structure for a given pfn. We need to check
273 * that both the top and mid levels are allocated, and make sure the
274 * parallel mfn tree is kept in sync. We may race with other cpus, so
275 * the new pages are installed with cmpxchg; if we lose the race then
276 * simply free the page we allocated and use the one that's there.
277 */
278static bool alloc_p2m(unsigned long pfn)
279{
280 unsigned topidx, mididx;
281 unsigned long ***top_p, **mid;
282 unsigned long *top_mfn_p, *mid_mfn;
283
284 topidx = p2m_top_index(pfn);
285 mididx = p2m_mid_index(pfn);
286
287 top_p = &p2m_top[topidx];
288 mid = *top_p;
289
290 if (mid == p2m_mid_missing) {
291 /* Mid level is missing, allocate a new one */
292 mid = alloc_p2m_page();
293 if (!mid)
294 return false;
295
296 p2m_mid_init(mid);
297
298 if (cmpxchg(top_p, p2m_mid_missing, mid) != p2m_mid_missing)
299 free_p2m_page(mid);
300 }
301
302 top_mfn_p = &p2m_top_mfn[topidx];
303 mid_mfn = p2m_top_mfn_p[topidx];
304
305 BUG_ON(virt_to_mfn(mid_mfn) != *top_mfn_p);
306
307 if (mid_mfn == p2m_mid_missing_mfn) {
308 /* Separately check the mid mfn level */
309 unsigned long missing_mfn;
310 unsigned long mid_mfn_mfn;
311
312 mid_mfn = alloc_p2m_page();
313 if (!mid_mfn)
314 return false;
315
316 p2m_mid_mfn_init(mid_mfn);
317
318 missing_mfn = virt_to_mfn(p2m_mid_missing_mfn);
319 mid_mfn_mfn = virt_to_mfn(mid_mfn);
320 if (cmpxchg(top_mfn_p, missing_mfn, mid_mfn_mfn) != missing_mfn)
321 free_p2m_page(mid_mfn);
322 else
323 p2m_top_mfn_p[topidx] = mid_mfn;
324 }
325
326 if (p2m_top[topidx][mididx] == p2m_missing) {
327 /* p2m leaf page is missing */
328 unsigned long *p2m;
329
330 p2m = alloc_p2m_page();
331 if (!p2m)
332 return false;
333
334 p2m_init(p2m);
335
336 if (cmpxchg(&mid[mididx], p2m_missing, p2m) != p2m_missing)
337 free_p2m_page(p2m);
338 else
339 mid_mfn[mididx] = virt_to_mfn(p2m);
340 }
341
342 return true;
343}
344
345/* Try to install p2m mapping; fail if intermediate bits missing */
346bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
347{
348 unsigned topidx, mididx, idx;
349
350 if (unlikely(pfn >= MAX_P2M_PFN)) {
351 BUG_ON(mfn != INVALID_P2M_ENTRY);
352 return true;
353 }
354
355 topidx = p2m_top_index(pfn);
356 mididx = p2m_mid_index(pfn);
357 idx = p2m_index(pfn);
358
359 if (p2m_top[topidx][mididx] == p2m_missing)
360 return mfn == INVALID_P2M_ENTRY;
361
362 p2m_top[topidx][mididx][idx] = mfn;
363
364 return true;
365}
366
367bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
368{
369 if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) {
370 BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
371 return true;
372 }
373
374 if (unlikely(!__set_phys_to_machine(pfn, mfn))) {
375 if (!alloc_p2m(pfn))
376 return false;
377
378 if (!__set_phys_to_machine(pfn, mfn))
379 return false;
380 }
381
382 return true;
383}
384
385#define M2P_OVERRIDE_HASH_SHIFT 10
386#define M2P_OVERRIDE_HASH (1 << M2P_OVERRIDE_HASH_SHIFT)
387
388static RESERVE_BRK_ARRAY(struct list_head, m2p_overrides, M2P_OVERRIDE_HASH);
389static DEFINE_SPINLOCK(m2p_override_lock);
390
391static void __init m2p_override_init(void)
392{
393 unsigned i;
394
395 m2p_overrides = extend_brk(sizeof(*m2p_overrides) * M2P_OVERRIDE_HASH,
396 sizeof(unsigned long));
397
398 for (i = 0; i < M2P_OVERRIDE_HASH; i++)
399 INIT_LIST_HEAD(&m2p_overrides[i]);
400}
401
402static unsigned long mfn_hash(unsigned long mfn)
403{
404 return hash_long(mfn, M2P_OVERRIDE_HASH_SHIFT);
405}
406
407/* Add an MFN override for a particular page */
408int m2p_add_override(unsigned long mfn, struct page *page)
409{
410 unsigned long flags;
411 unsigned long pfn;
412 unsigned long address;
413 unsigned level;
414 pte_t *ptep = NULL;
415
416 pfn = page_to_pfn(page);
417 if (!PageHighMem(page)) {
418 address = (unsigned long)__va(pfn << PAGE_SHIFT);
419 ptep = lookup_address(address, &level);
420
421 if (WARN(ptep == NULL || level != PG_LEVEL_4K,
422 "m2p_add_override: pfn %lx not mapped", pfn))
423 return -EINVAL;
424 }
425
426 page->private = mfn;
427 page->index = pfn_to_mfn(pfn);
428
429 __set_phys_to_machine(pfn, FOREIGN_FRAME(mfn));
430 if (!PageHighMem(page))
431 /* Just zap old mapping for now */
432 pte_clear(&init_mm, address, ptep);
433
434 spin_lock_irqsave(&m2p_override_lock, flags);
435 list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]);
436 spin_unlock_irqrestore(&m2p_override_lock, flags);
437
438 return 0;
439}
440
441int m2p_remove_override(struct page *page)
442{
443 unsigned long flags;
444 unsigned long mfn;
445 unsigned long pfn;
446 unsigned long address;
447 unsigned level;
448 pte_t *ptep = NULL;
449
450 pfn = page_to_pfn(page);
451 mfn = get_phys_to_machine(pfn);
452 if (mfn == INVALID_P2M_ENTRY || !(mfn & FOREIGN_FRAME_BIT))
453 return -EINVAL;
454
455 if (!PageHighMem(page)) {
456 address = (unsigned long)__va(pfn << PAGE_SHIFT);
457 ptep = lookup_address(address, &level);
458
459 if (WARN(ptep == NULL || level != PG_LEVEL_4K,
460 "m2p_remove_override: pfn %lx not mapped", pfn))
461 return -EINVAL;
462 }
463
464 spin_lock_irqsave(&m2p_override_lock, flags);
465 list_del(&page->lru);
466 spin_unlock_irqrestore(&m2p_override_lock, flags);
467 __set_phys_to_machine(pfn, page->index);
468
469 if (!PageHighMem(page))
470 set_pte_at(&init_mm, address, ptep,
471 pfn_pte(pfn, PAGE_KERNEL));
472 /* No tlb flush necessary because the caller already
473 * left the pte unmapped. */
474
475 return 0;
476}
477
478struct page *m2p_find_override(unsigned long mfn)
479{
480 unsigned long flags;
481 struct list_head *bucket = &m2p_overrides[mfn_hash(mfn)];
482 struct page *p, *ret;
483
484 ret = NULL;
485
486 spin_lock_irqsave(&m2p_override_lock, flags);
487
488 list_for_each_entry(p, bucket, lru) {
489 if (p->private == mfn) {
490 ret = p;
491 break;
492 }
493 }
494
495 spin_unlock_irqrestore(&m2p_override_lock, flags);
496
497 return ret;
498}
499
500unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn)
501{
502 struct page *p = m2p_find_override(mfn);
503 unsigned long ret = pfn;
504
505 if (p)
506 ret = page_to_pfn(p);
507
508 return ret;
509}
510EXPORT_SYMBOL_GPL(m2p_find_override_pfn);
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
index 464d8935ad4e..07bec09d1dad 100644
--- a/drivers/xen/Kconfig
+++ b/drivers/xen/Kconfig
@@ -71,7 +71,14 @@ config XEN_SYS_HYPERVISOR
71 but will have no xen contents. 71 but will have no xen contents.
72 72
73config XEN_XENBUS_FRONTEND 73config XEN_XENBUS_FRONTEND
74 tristate 74 tristate
75
76config XEN_GNTDEV
77 tristate "userspace grant access device driver"
78 depends on XEN
79 select MMU_NOTIFIER
80 help
81 Allows userspace processes to use grants.
75 82
76config XEN_PLATFORM_PCI 83config XEN_PLATFORM_PCI
77 tristate "xen platform pci device driver" 84 tristate "xen platform pci device driver"
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
index f81819b0f916..5088cc2e6fe2 100644
--- a/drivers/xen/Makefile
+++ b/drivers/xen/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o
9obj-$(CONFIG_XEN_XENCOMM) += xencomm.o 9obj-$(CONFIG_XEN_XENCOMM) += xencomm.o
10obj-$(CONFIG_XEN_BALLOON) += balloon.o 10obj-$(CONFIG_XEN_BALLOON) += balloon.o
11obj-$(CONFIG_XEN_DEV_EVTCHN) += xen-evtchn.o 11obj-$(CONFIG_XEN_DEV_EVTCHN) += xen-evtchn.o
12obj-$(CONFIG_XEN_GNTDEV) += xen-gntdev.o
12obj-$(CONFIG_XENFS) += xenfs/ 13obj-$(CONFIG_XENFS) += xenfs/
13obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o 14obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o
14obj-$(CONFIG_XEN_PLATFORM_PCI) += xen-platform-pci.o 15obj-$(CONFIG_XEN_PLATFORM_PCI) += xen-platform-pci.o
@@ -16,5 +17,6 @@ obj-$(CONFIG_SWIOTLB_XEN) += swiotlb-xen.o
16obj-$(CONFIG_XEN_DOM0) += pci.o 17obj-$(CONFIG_XEN_DOM0) += pci.o
17 18
18xen-evtchn-y := evtchn.o 19xen-evtchn-y := evtchn.o
20xen-gntdev-y := gntdev.o
19 21
20xen-platform-pci-y := platform-pci.o 22xen-platform-pci-y := platform-pci.o
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
new file mode 100644
index 000000000000..1e31cdcdae1e
--- /dev/null
+++ b/drivers/xen/gntdev.c
@@ -0,0 +1,665 @@
1/******************************************************************************
2 * gntdev.c
3 *
4 * Device for accessing (in user-space) pages that have been granted by other
5 * domains.
6 *
7 * Copyright (c) 2006-2007, D G Murray.
8 * (c) 2009 Gerd Hoffmann <kraxel@redhat.com>
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#undef DEBUG
21
22#include <linux/module.h>
23#include <linux/kernel.h>
24#include <linux/init.h>
25#include <linux/miscdevice.h>
26#include <linux/fs.h>
27#include <linux/mm.h>
28#include <linux/mman.h>
29#include <linux/mmu_notifier.h>
30#include <linux/types.h>
31#include <linux/uaccess.h>
32#include <linux/sched.h>
33#include <linux/spinlock.h>
34#include <linux/slab.h>
35
36#include <xen/xen.h>
37#include <xen/grant_table.h>
38#include <xen/gntdev.h>
39#include <asm/xen/hypervisor.h>
40#include <asm/xen/hypercall.h>
41#include <asm/xen/page.h>
42
43MODULE_LICENSE("GPL");
44MODULE_AUTHOR("Derek G. Murray <Derek.Murray@cl.cam.ac.uk>, "
45 "Gerd Hoffmann <kraxel@redhat.com>");
46MODULE_DESCRIPTION("User-space granted page access driver");
47
48static int limit = 1024;
49module_param(limit, int, 0644);
50MODULE_PARM_DESC(limit, "Maximum number of grants that may be mapped at "
51 "once by a gntdev instance");
52
53struct gntdev_priv {
54 struct list_head maps;
55 uint32_t used;
56 uint32_t limit;
57 /* lock protects maps from concurrent changes */
58 spinlock_t lock;
59 struct mm_struct *mm;
60 struct mmu_notifier mn;
61};
62
63struct grant_map {
64 struct list_head next;
65 struct gntdev_priv *priv;
66 struct vm_area_struct *vma;
67 int index;
68 int count;
69 int flags;
70 int is_mapped;
71 struct ioctl_gntdev_grant_ref *grants;
72 struct gnttab_map_grant_ref *map_ops;
73 struct gnttab_unmap_grant_ref *unmap_ops;
74 struct page **pages;
75};
76
77/* ------------------------------------------------------------------ */
78
79static void gntdev_print_maps(struct gntdev_priv *priv,
80 char *text, int text_index)
81{
82#ifdef DEBUG
83 struct grant_map *map;
84
85 pr_debug("maps list (priv %p, usage %d/%d)\n",
86 priv, priv->used, priv->limit);
87
88 list_for_each_entry(map, &priv->maps, next)
89 pr_debug(" index %2d, count %2d %s\n",
90 map->index, map->count,
91 map->index == text_index && text ? text : "");
92#endif
93}
94
95static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)
96{
97 struct grant_map *add;
98 int i;
99
100 add = kzalloc(sizeof(struct grant_map), GFP_KERNEL);
101 if (NULL == add)
102 return NULL;
103
104 add->grants = kzalloc(sizeof(add->grants[0]) * count, GFP_KERNEL);
105 add->map_ops = kzalloc(sizeof(add->map_ops[0]) * count, GFP_KERNEL);
106 add->unmap_ops = kzalloc(sizeof(add->unmap_ops[0]) * count, GFP_KERNEL);
107 add->pages = kzalloc(sizeof(add->pages[0]) * count, GFP_KERNEL);
108 if (NULL == add->grants ||
109 NULL == add->map_ops ||
110 NULL == add->unmap_ops ||
111 NULL == add->pages)
112 goto err;
113
114 for (i = 0; i < count; i++) {
115 add->pages[i] = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
116 if (add->pages[i] == NULL)
117 goto err;
118 }
119
120 add->index = 0;
121 add->count = count;
122 add->priv = priv;
123
124 if (add->count + priv->used > priv->limit)
125 goto err;
126
127 return add;
128
129err:
130 if (add->pages)
131 for (i = 0; i < count; i++) {
132 if (add->pages[i])
133 __free_page(add->pages[i]);
134 }
135 kfree(add->pages);
136 kfree(add->grants);
137 kfree(add->map_ops);
138 kfree(add->unmap_ops);
139 kfree(add);
140 return NULL;
141}
142
143static void gntdev_add_map(struct gntdev_priv *priv, struct grant_map *add)
144{
145 struct grant_map *map;
146
147 list_for_each_entry(map, &priv->maps, next) {
148 if (add->index + add->count < map->index) {
149 list_add_tail(&add->next, &map->next);
150 goto done;
151 }
152 add->index = map->index + map->count;
153 }
154 list_add_tail(&add->next, &priv->maps);
155
156done:
157 priv->used += add->count;
158 gntdev_print_maps(priv, "[new]", add->index);
159}
160
161static struct grant_map *gntdev_find_map_index(struct gntdev_priv *priv,
162 int index, int count)
163{
164 struct grant_map *map;
165
166 list_for_each_entry(map, &priv->maps, next) {
167 if (map->index != index)
168 continue;
169 if (map->count != count)
170 continue;
171 return map;
172 }
173 return NULL;
174}
175
176static struct grant_map *gntdev_find_map_vaddr(struct gntdev_priv *priv,
177 unsigned long vaddr)
178{
179 struct grant_map *map;
180
181 list_for_each_entry(map, &priv->maps, next) {
182 if (!map->vma)
183 continue;
184 if (vaddr < map->vma->vm_start)
185 continue;
186 if (vaddr >= map->vma->vm_end)
187 continue;
188 return map;
189 }
190 return NULL;
191}
192
193static int gntdev_del_map(struct grant_map *map)
194{
195 int i;
196
197 if (map->vma)
198 return -EBUSY;
199 for (i = 0; i < map->count; i++)
200 if (map->unmap_ops[i].handle)
201 return -EBUSY;
202
203 map->priv->used -= map->count;
204 list_del(&map->next);
205 return 0;
206}
207
208static void gntdev_free_map(struct grant_map *map)
209{
210 int i;
211
212 if (!map)
213 return;
214
215 if (map->pages)
216 for (i = 0; i < map->count; i++) {
217 if (map->pages[i])
218 __free_page(map->pages[i]);
219 }
220 kfree(map->pages);
221 kfree(map->grants);
222 kfree(map->map_ops);
223 kfree(map->unmap_ops);
224 kfree(map);
225}
226
227/* ------------------------------------------------------------------ */
228
229static int find_grant_ptes(pte_t *pte, pgtable_t token,
230 unsigned long addr, void *data)
231{
232 struct grant_map *map = data;
233 unsigned int pgnr = (addr - map->vma->vm_start) >> PAGE_SHIFT;
234 u64 pte_maddr;
235
236 BUG_ON(pgnr >= map->count);
237 pte_maddr = arbitrary_virt_to_machine(pte).maddr;
238
239 gnttab_set_map_op(&map->map_ops[pgnr], pte_maddr,
240 GNTMAP_contains_pte | map->flags,
241 map->grants[pgnr].ref,
242 map->grants[pgnr].domid);
243 gnttab_set_unmap_op(&map->unmap_ops[pgnr], pte_maddr,
244 GNTMAP_contains_pte | map->flags,
245 0 /* handle */);
246 return 0;
247}
248
249static int map_grant_pages(struct grant_map *map)
250{
251 int i, err = 0;
252
253 pr_debug("map %d+%d\n", map->index, map->count);
254 err = gnttab_map_refs(map->map_ops, map->pages, map->count);
255 if (err)
256 return err;
257
258 for (i = 0; i < map->count; i++) {
259 if (map->map_ops[i].status)
260 err = -EINVAL;
261 map->unmap_ops[i].handle = map->map_ops[i].handle;
262 }
263 return err;
264}
265
266static int unmap_grant_pages(struct grant_map *map, int offset, int pages)
267{
268 int i, err = 0;
269
270 pr_debug("map %d+%d [%d+%d]\n", map->index, map->count, offset, pages);
271 err = gnttab_unmap_refs(map->unmap_ops + offset, map->pages, pages);
272 if (err)
273 return err;
274
275 for (i = 0; i < pages; i++) {
276 if (map->unmap_ops[offset+i].status)
277 err = -EINVAL;
278 map->unmap_ops[offset+i].handle = 0;
279 }
280 return err;
281}
282
283/* ------------------------------------------------------------------ */
284
285static void gntdev_vma_close(struct vm_area_struct *vma)
286{
287 struct grant_map *map = vma->vm_private_data;
288
289 pr_debug("close %p\n", vma);
290 map->is_mapped = 0;
291 map->vma = NULL;
292 vma->vm_private_data = NULL;
293}
294
295static int gntdev_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
296{
297 pr_debug("vaddr %p, pgoff %ld (shouldn't happen)\n",
298 vmf->virtual_address, vmf->pgoff);
299 vmf->flags = VM_FAULT_ERROR;
300 return 0;
301}
302
303static struct vm_operations_struct gntdev_vmops = {
304 .close = gntdev_vma_close,
305 .fault = gntdev_vma_fault,
306};
307
308/* ------------------------------------------------------------------ */
309
310static void mn_invl_range_start(struct mmu_notifier *mn,
311 struct mm_struct *mm,
312 unsigned long start, unsigned long end)
313{
314 struct gntdev_priv *priv = container_of(mn, struct gntdev_priv, mn);
315 struct grant_map *map;
316 unsigned long mstart, mend;
317 int err;
318
319 spin_lock(&priv->lock);
320 list_for_each_entry(map, &priv->maps, next) {
321 if (!map->vma)
322 continue;
323 if (!map->is_mapped)
324 continue;
325 if (map->vma->vm_start >= end)
326 continue;
327 if (map->vma->vm_end <= start)
328 continue;
329 mstart = max(start, map->vma->vm_start);
330 mend = min(end, map->vma->vm_end);
331 pr_debug("map %d+%d (%lx %lx), range %lx %lx, mrange %lx %lx\n",
332 map->index, map->count,
333 map->vma->vm_start, map->vma->vm_end,
334 start, end, mstart, mend);
335 err = unmap_grant_pages(map,
336 (mstart - map->vma->vm_start) >> PAGE_SHIFT,
337 (mend - mstart) >> PAGE_SHIFT);
338 WARN_ON(err);
339 }
340 spin_unlock(&priv->lock);
341}
342
343static void mn_invl_page(struct mmu_notifier *mn,
344 struct mm_struct *mm,
345 unsigned long address)
346{
347 mn_invl_range_start(mn, mm, address, address + PAGE_SIZE);
348}
349
350static void mn_release(struct mmu_notifier *mn,
351 struct mm_struct *mm)
352{
353 struct gntdev_priv *priv = container_of(mn, struct gntdev_priv, mn);
354 struct grant_map *map;
355 int err;
356
357 spin_lock(&priv->lock);
358 list_for_each_entry(map, &priv->maps, next) {
359 if (!map->vma)
360 continue;
361 pr_debug("map %d+%d (%lx %lx)\n",
362 map->index, map->count,
363 map->vma->vm_start, map->vma->vm_end);
364 err = unmap_grant_pages(map, /* offset */ 0, map->count);
365 WARN_ON(err);
366 }
367 spin_unlock(&priv->lock);
368}
369
370struct mmu_notifier_ops gntdev_mmu_ops = {
371 .release = mn_release,
372 .invalidate_page = mn_invl_page,
373 .invalidate_range_start = mn_invl_range_start,
374};
375
376/* ------------------------------------------------------------------ */
377
378static int gntdev_open(struct inode *inode, struct file *flip)
379{
380 struct gntdev_priv *priv;
381 int ret = 0;
382
383 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
384 if (!priv)
385 return -ENOMEM;
386
387 INIT_LIST_HEAD(&priv->maps);
388 spin_lock_init(&priv->lock);
389 priv->limit = limit;
390
391 priv->mm = get_task_mm(current);
392 if (!priv->mm) {
393 kfree(priv);
394 return -ENOMEM;
395 }
396 priv->mn.ops = &gntdev_mmu_ops;
397 ret = mmu_notifier_register(&priv->mn, priv->mm);
398 mmput(priv->mm);
399
400 if (ret) {
401 kfree(priv);
402 return ret;
403 }
404
405 flip->private_data = priv;
406 pr_debug("priv %p\n", priv);
407
408 return 0;
409}
410
411static int gntdev_release(struct inode *inode, struct file *flip)
412{
413 struct gntdev_priv *priv = flip->private_data;
414 struct grant_map *map;
415 int err;
416
417 pr_debug("priv %p\n", priv);
418
419 spin_lock(&priv->lock);
420 while (!list_empty(&priv->maps)) {
421 map = list_entry(priv->maps.next, struct grant_map, next);
422 err = gntdev_del_map(map);
423 if (WARN_ON(err))
424 gntdev_free_map(map);
425
426 }
427 spin_unlock(&priv->lock);
428
429 mmu_notifier_unregister(&priv->mn, priv->mm);
430 kfree(priv);
431 return 0;
432}
433
434static long gntdev_ioctl_map_grant_ref(struct gntdev_priv *priv,
435 struct ioctl_gntdev_map_grant_ref __user *u)
436{
437 struct ioctl_gntdev_map_grant_ref op;
438 struct grant_map *map;
439 int err;
440
441 if (copy_from_user(&op, u, sizeof(op)) != 0)
442 return -EFAULT;
443 pr_debug("priv %p, add %d\n", priv, op.count);
444 if (unlikely(op.count <= 0))
445 return -EINVAL;
446 if (unlikely(op.count > priv->limit))
447 return -EINVAL;
448
449 err = -ENOMEM;
450 map = gntdev_alloc_map(priv, op.count);
451 if (!map)
452 return err;
453 if (copy_from_user(map->grants, &u->refs,
454 sizeof(map->grants[0]) * op.count) != 0) {
455 gntdev_free_map(map);
456 return err;
457 }
458
459 spin_lock(&priv->lock);
460 gntdev_add_map(priv, map);
461 op.index = map->index << PAGE_SHIFT;
462 spin_unlock(&priv->lock);
463
464 if (copy_to_user(u, &op, sizeof(op)) != 0) {
465 spin_lock(&priv->lock);
466 gntdev_del_map(map);
467 spin_unlock(&priv->lock);
468 gntdev_free_map(map);
469 return err;
470 }
471 return 0;
472}
473
474static long gntdev_ioctl_unmap_grant_ref(struct gntdev_priv *priv,
475 struct ioctl_gntdev_unmap_grant_ref __user *u)
476{
477 struct ioctl_gntdev_unmap_grant_ref op;
478 struct grant_map *map;
479 int err = -ENOENT;
480
481 if (copy_from_user(&op, u, sizeof(op)) != 0)
482 return -EFAULT;
483 pr_debug("priv %p, del %d+%d\n", priv, (int)op.index, (int)op.count);
484
485 spin_lock(&priv->lock);
486 map = gntdev_find_map_index(priv, op.index >> PAGE_SHIFT, op.count);
487 if (map)
488 err = gntdev_del_map(map);
489 spin_unlock(&priv->lock);
490 if (!err)
491 gntdev_free_map(map);
492 return err;
493}
494
495static long gntdev_ioctl_get_offset_for_vaddr(struct gntdev_priv *priv,
496 struct ioctl_gntdev_get_offset_for_vaddr __user *u)
497{
498 struct ioctl_gntdev_get_offset_for_vaddr op;
499 struct grant_map *map;
500
501 if (copy_from_user(&op, u, sizeof(op)) != 0)
502 return -EFAULT;
503 pr_debug("priv %p, offset for vaddr %lx\n", priv, (unsigned long)op.vaddr);
504
505 spin_lock(&priv->lock);
506 map = gntdev_find_map_vaddr(priv, op.vaddr);
507 if (map == NULL ||
508 map->vma->vm_start != op.vaddr) {
509 spin_unlock(&priv->lock);
510 return -EINVAL;
511 }
512 op.offset = map->index << PAGE_SHIFT;
513 op.count = map->count;
514 spin_unlock(&priv->lock);
515
516 if (copy_to_user(u, &op, sizeof(op)) != 0)
517 return -EFAULT;
518 return 0;
519}
520
521static long gntdev_ioctl_set_max_grants(struct gntdev_priv *priv,
522 struct ioctl_gntdev_set_max_grants __user *u)
523{
524 struct ioctl_gntdev_set_max_grants op;
525
526 if (copy_from_user(&op, u, sizeof(op)) != 0)
527 return -EFAULT;
528 pr_debug("priv %p, limit %d\n", priv, op.count);
529 if (op.count > limit)
530 return -E2BIG;
531
532 spin_lock(&priv->lock);
533 priv->limit = op.count;
534 spin_unlock(&priv->lock);
535 return 0;
536}
537
538static long gntdev_ioctl(struct file *flip,
539 unsigned int cmd, unsigned long arg)
540{
541 struct gntdev_priv *priv = flip->private_data;
542 void __user *ptr = (void __user *)arg;
543
544 switch (cmd) {
545 case IOCTL_GNTDEV_MAP_GRANT_REF:
546 return gntdev_ioctl_map_grant_ref(priv, ptr);
547
548 case IOCTL_GNTDEV_UNMAP_GRANT_REF:
549 return gntdev_ioctl_unmap_grant_ref(priv, ptr);
550
551 case IOCTL_GNTDEV_GET_OFFSET_FOR_VADDR:
552 return gntdev_ioctl_get_offset_for_vaddr(priv, ptr);
553
554 case IOCTL_GNTDEV_SET_MAX_GRANTS:
555 return gntdev_ioctl_set_max_grants(priv, ptr);
556
557 default:
558 pr_debug("priv %p, unknown cmd %x\n", priv, cmd);
559 return -ENOIOCTLCMD;
560 }
561
562 return 0;
563}
564
565static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
566{
567 struct gntdev_priv *priv = flip->private_data;
568 int index = vma->vm_pgoff;
569 int count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
570 struct grant_map *map;
571 int err = -EINVAL;
572
573 if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED))
574 return -EINVAL;
575
576 pr_debug("map %d+%d at %lx (pgoff %lx)\n",
577 index, count, vma->vm_start, vma->vm_pgoff);
578
579 spin_lock(&priv->lock);
580 map = gntdev_find_map_index(priv, index, count);
581 if (!map)
582 goto unlock_out;
583 if (map->vma)
584 goto unlock_out;
585 if (priv->mm != vma->vm_mm) {
586 printk(KERN_WARNING "Huh? Other mm?\n");
587 goto unlock_out;
588 }
589
590 vma->vm_ops = &gntdev_vmops;
591
592 vma->vm_flags |= VM_RESERVED|VM_DONTCOPY|VM_DONTEXPAND|VM_PFNMAP;
593
594 vma->vm_private_data = map;
595 map->vma = vma;
596
597 map->flags = GNTMAP_host_map | GNTMAP_application_map;
598 if (!(vma->vm_flags & VM_WRITE))
599 map->flags |= GNTMAP_readonly;
600
601 spin_unlock(&priv->lock);
602
603 err = apply_to_page_range(vma->vm_mm, vma->vm_start,
604 vma->vm_end - vma->vm_start,
605 find_grant_ptes, map);
606 if (err) {
607 printk(KERN_WARNING "find_grant_ptes() failure.\n");
608 return err;
609 }
610
611 err = map_grant_pages(map);
612 if (err) {
613 printk(KERN_WARNING "map_grant_pages() failure.\n");
614 return err;
615 }
616
617 map->is_mapped = 1;
618
619 return 0;
620
621unlock_out:
622 spin_unlock(&priv->lock);
623 return err;
624}
625
626static const struct file_operations gntdev_fops = {
627 .owner = THIS_MODULE,
628 .open = gntdev_open,
629 .release = gntdev_release,
630 .mmap = gntdev_mmap,
631 .unlocked_ioctl = gntdev_ioctl
632};
633
634static struct miscdevice gntdev_miscdev = {
635 .minor = MISC_DYNAMIC_MINOR,
636 .name = "xen/gntdev",
637 .fops = &gntdev_fops,
638};
639
640/* ------------------------------------------------------------------ */
641
642static int __init gntdev_init(void)
643{
644 int err;
645
646 if (!xen_domain())
647 return -ENODEV;
648
649 err = misc_register(&gntdev_miscdev);
650 if (err != 0) {
651 printk(KERN_ERR "Could not register gntdev device\n");
652 return err;
653 }
654 return 0;
655}
656
657static void __exit gntdev_exit(void)
658{
659 misc_deregister(&gntdev_miscdev);
660}
661
662module_init(gntdev_init);
663module_exit(gntdev_exit);
664
665/* ------------------------------------------------------------------ */
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index 6c4531816496..9ef54ebc1194 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -447,6 +447,52 @@ unsigned int gnttab_max_grant_frames(void)
447} 447}
448EXPORT_SYMBOL_GPL(gnttab_max_grant_frames); 448EXPORT_SYMBOL_GPL(gnttab_max_grant_frames);
449 449
450int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
451 struct page **pages, unsigned int count)
452{
453 int i, ret;
454 pte_t *pte;
455 unsigned long mfn;
456
457 ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map_ops, count);
458 if (ret)
459 return ret;
460
461 for (i = 0; i < count; i++) {
462 /* m2p override only supported for GNTMAP_contains_pte mappings */
463 if (!(map_ops[i].flags & GNTMAP_contains_pte))
464 continue;
465 pte = (pte_t *) (mfn_to_virt(PFN_DOWN(map_ops[i].host_addr)) +
466 (map_ops[i].host_addr & ~PAGE_MASK));
467 mfn = pte_mfn(*pte);
468 ret = m2p_add_override(mfn, pages[i]);
469 if (ret)
470 return ret;
471 }
472
473 return ret;
474}
475EXPORT_SYMBOL_GPL(gnttab_map_refs);
476
477int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
478 struct page **pages, unsigned int count)
479{
480 int i, ret;
481
482 ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap_ops, count);
483 if (ret)
484 return ret;
485
486 for (i = 0; i < count; i++) {
487 ret = m2p_remove_override(pages[i]);
488 if (ret)
489 return ret;
490 }
491
492 return ret;
493}
494EXPORT_SYMBOL_GPL(gnttab_unmap_refs);
495
450static int gnttab_map(unsigned int start_idx, unsigned int end_idx) 496static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
451{ 497{
452 struct gnttab_setup_table setup; 498 struct gnttab_setup_table setup;
diff --git a/include/xen/gntdev.h b/include/xen/gntdev.h
new file mode 100644
index 000000000000..eb23f4188f5a
--- /dev/null
+++ b/include/xen/gntdev.h
@@ -0,0 +1,119 @@
1/******************************************************************************
2 * gntdev.h
3 *
4 * Interface to /dev/xen/gntdev.
5 *
6 * Copyright (c) 2007, D G Murray
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation; or, when distributed
11 * separately from the Linux kernel or incorporated into other
12 * software packages, subject to the following license:
13 *
14 * Permission is hereby granted, free of charge, to any person obtaining a copy
15 * of this source file (the "Software"), to deal in the Software without
16 * restriction, including without limitation the rights to use, copy, modify,
17 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
18 * and to permit persons to whom the Software is furnished to do so, subject to
19 * the following conditions:
20 *
21 * The above copyright notice and this permission notice shall be included in
22 * all copies or substantial portions of the Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30 * IN THE SOFTWARE.
31 */
32
33#ifndef __LINUX_PUBLIC_GNTDEV_H__
34#define __LINUX_PUBLIC_GNTDEV_H__
35
36struct ioctl_gntdev_grant_ref {
37 /* The domain ID of the grant to be mapped. */
38 uint32_t domid;
39 /* The grant reference of the grant to be mapped. */
40 uint32_t ref;
41};
42
43/*
44 * Inserts the grant references into the mapping table of an instance
45 * of gntdev. N.B. This does not perform the mapping, which is deferred
46 * until mmap() is called with @index as the offset.
47 */
48#define IOCTL_GNTDEV_MAP_GRANT_REF \
49_IOC(_IOC_NONE, 'G', 0, sizeof(struct ioctl_gntdev_map_grant_ref))
50struct ioctl_gntdev_map_grant_ref {
51 /* IN parameters */
52 /* The number of grants to be mapped. */
53 uint32_t count;
54 uint32_t pad;
55 /* OUT parameters */
56 /* The offset to be used on a subsequent call to mmap(). */
57 uint64_t index;
58 /* Variable IN parameter. */
59 /* Array of grant references, of size @count. */
60 struct ioctl_gntdev_grant_ref refs[1];
61};
62
63/*
64 * Removes the grant references from the mapping table of an instance of
65 * of gntdev. N.B. munmap() must be called on the relevant virtual address(es)
66 * before this ioctl is called, or an error will result.
67 */
68#define IOCTL_GNTDEV_UNMAP_GRANT_REF \
69_IOC(_IOC_NONE, 'G', 1, sizeof(struct ioctl_gntdev_unmap_grant_ref))
70struct ioctl_gntdev_unmap_grant_ref {
71 /* IN parameters */
72 /* The offset was returned by the corresponding map operation. */
73 uint64_t index;
74 /* The number of pages to be unmapped. */
75 uint32_t count;
76 uint32_t pad;
77};
78
79/*
80 * Returns the offset in the driver's address space that corresponds
81 * to @vaddr. This can be used to perform a munmap(), followed by an
82 * UNMAP_GRANT_REF ioctl, where no state about the offset is retained by
83 * the caller. The number of pages that were allocated at the same time as
84 * @vaddr is returned in @count.
85 *
86 * N.B. Where more than one page has been mapped into a contiguous range, the
87 * supplied @vaddr must correspond to the start of the range; otherwise
88 * an error will result. It is only possible to munmap() the entire
89 * contiguously-allocated range at once, and not any subrange thereof.
90 */
91#define IOCTL_GNTDEV_GET_OFFSET_FOR_VADDR \
92_IOC(_IOC_NONE, 'G', 2, sizeof(struct ioctl_gntdev_get_offset_for_vaddr))
93struct ioctl_gntdev_get_offset_for_vaddr {
94 /* IN parameters */
95 /* The virtual address of the first mapped page in a range. */
96 uint64_t vaddr;
97 /* OUT parameters */
98 /* The offset that was used in the initial mmap() operation. */
99 uint64_t offset;
100 /* The number of pages mapped in the VM area that begins at @vaddr. */
101 uint32_t count;
102 uint32_t pad;
103};
104
105/*
106 * Sets the maximum number of grants that may mapped at once by this gntdev
107 * instance.
108 *
109 * N.B. This must be called before any other ioctl is performed on the device.
110 */
111#define IOCTL_GNTDEV_SET_MAX_GRANTS \
112_IOC(_IOC_NONE, 'G', 3, sizeof(struct ioctl_gntdev_set_max_grants))
113struct ioctl_gntdev_set_max_grants {
114 /* IN parameter */
115 /* The maximum number of grants that may be mapped at once. */
116 uint32_t count;
117};
118
119#endif /* __LINUX_PUBLIC_GNTDEV_H__ */
diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h
index 9a731706a016..b1fab6b5b3ef 100644
--- a/include/xen/grant_table.h
+++ b/include/xen/grant_table.h
@@ -37,10 +37,16 @@
37#ifndef __ASM_GNTTAB_H__ 37#ifndef __ASM_GNTTAB_H__
38#define __ASM_GNTTAB_H__ 38#define __ASM_GNTTAB_H__
39 39
40#include <asm/xen/hypervisor.h> 40#include <asm/page.h>
41
42#include <xen/interface/xen.h>
41#include <xen/interface/grant_table.h> 43#include <xen/interface/grant_table.h>
44
45#include <asm/xen/hypervisor.h>
42#include <asm/xen/grant_table.h> 46#include <asm/xen/grant_table.h>
43 47
48#include <xen/features.h>
49
44/* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */ 50/* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */
45#define NR_GRANT_FRAMES 4 51#define NR_GRANT_FRAMES 4
46 52
@@ -107,6 +113,37 @@ void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
107void gnttab_grant_foreign_transfer_ref(grant_ref_t, domid_t domid, 113void gnttab_grant_foreign_transfer_ref(grant_ref_t, domid_t domid,
108 unsigned long pfn); 114 unsigned long pfn);
109 115
116static inline void
117gnttab_set_map_op(struct gnttab_map_grant_ref *map, phys_addr_t addr,
118 uint32_t flags, grant_ref_t ref, domid_t domid)
119{
120 if (flags & GNTMAP_contains_pte)
121 map->host_addr = addr;
122 else if (xen_feature(XENFEAT_auto_translated_physmap))
123 map->host_addr = __pa(addr);
124 else
125 map->host_addr = addr;
126
127 map->flags = flags;
128 map->ref = ref;
129 map->dom = domid;
130}
131
132static inline void
133gnttab_set_unmap_op(struct gnttab_unmap_grant_ref *unmap, phys_addr_t addr,
134 uint32_t flags, grant_handle_t handle)
135{
136 if (flags & GNTMAP_contains_pte)
137 unmap->host_addr = addr;
138 else if (xen_feature(XENFEAT_auto_translated_physmap))
139 unmap->host_addr = __pa(addr);
140 else
141 unmap->host_addr = addr;
142
143 unmap->handle = handle;
144 unmap->dev_bus_addr = 0;
145}
146
110int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes, 147int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
111 unsigned long max_nr_gframes, 148 unsigned long max_nr_gframes,
112 struct grant_entry **__shared); 149 struct grant_entry **__shared);
@@ -118,4 +155,9 @@ unsigned int gnttab_max_grant_frames(void);
118 155
119#define gnttab_map_vaddr(map) ((void *)(map.host_virt_addr)) 156#define gnttab_map_vaddr(map) ((void *)(map.host_virt_addr))
120 157
158int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
159 struct page **pages, unsigned int count);
160int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
161 struct page **pages, unsigned int count);
162
121#endif /* __ASM_GNTTAB_H__ */ 163#endif /* __ASM_GNTTAB_H__ */