diff options
Diffstat (limited to 'drivers/xen/grant-table.c')
-rw-r--r-- | drivers/xen/grant-table.c | 77 |
1 files changed, 67 insertions, 10 deletions
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index f66db3b91d61..6c4531816496 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c | |||
@@ -37,11 +37,13 @@ | |||
37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
38 | #include <linux/vmalloc.h> | 38 | #include <linux/vmalloc.h> |
39 | #include <linux/uaccess.h> | 39 | #include <linux/uaccess.h> |
40 | #include <linux/io.h> | ||
40 | 41 | ||
41 | #include <xen/xen.h> | 42 | #include <xen/xen.h> |
42 | #include <xen/interface/xen.h> | 43 | #include <xen/interface/xen.h> |
43 | #include <xen/page.h> | 44 | #include <xen/page.h> |
44 | #include <xen/grant_table.h> | 45 | #include <xen/grant_table.h> |
46 | #include <xen/interface/memory.h> | ||
45 | #include <asm/xen/hypercall.h> | 47 | #include <asm/xen/hypercall.h> |
46 | 48 | ||
47 | #include <asm/pgtable.h> | 49 | #include <asm/pgtable.h> |
@@ -59,6 +61,8 @@ static unsigned int boot_max_nr_grant_frames; | |||
59 | static int gnttab_free_count; | 61 | static int gnttab_free_count; |
60 | static grant_ref_t gnttab_free_head; | 62 | static grant_ref_t gnttab_free_head; |
61 | static DEFINE_SPINLOCK(gnttab_list_lock); | 63 | static DEFINE_SPINLOCK(gnttab_list_lock); |
64 | unsigned long xen_hvm_resume_frames; | ||
65 | EXPORT_SYMBOL_GPL(xen_hvm_resume_frames); | ||
62 | 66 | ||
63 | static struct grant_entry *shared; | 67 | static struct grant_entry *shared; |
64 | 68 | ||
@@ -433,7 +437,7 @@ static unsigned int __max_nr_grant_frames(void) | |||
433 | return query.max_nr_frames; | 437 | return query.max_nr_frames; |
434 | } | 438 | } |
435 | 439 | ||
436 | static inline unsigned int max_nr_grant_frames(void) | 440 | unsigned int gnttab_max_grant_frames(void) |
437 | { | 441 | { |
438 | unsigned int xen_max = __max_nr_grant_frames(); | 442 | unsigned int xen_max = __max_nr_grant_frames(); |
439 | 443 | ||
@@ -441,6 +445,7 @@ static inline unsigned int max_nr_grant_frames(void) | |||
441 | return boot_max_nr_grant_frames; | 445 | return boot_max_nr_grant_frames; |
442 | return xen_max; | 446 | return xen_max; |
443 | } | 447 | } |
448 | EXPORT_SYMBOL_GPL(gnttab_max_grant_frames); | ||
444 | 449 | ||
445 | static int gnttab_map(unsigned int start_idx, unsigned int end_idx) | 450 | static int gnttab_map(unsigned int start_idx, unsigned int end_idx) |
446 | { | 451 | { |
@@ -449,6 +454,30 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx) | |||
449 | unsigned int nr_gframes = end_idx + 1; | 454 | unsigned int nr_gframes = end_idx + 1; |
450 | int rc; | 455 | int rc; |
451 | 456 | ||
457 | if (xen_hvm_domain()) { | ||
458 | struct xen_add_to_physmap xatp; | ||
459 | unsigned int i = end_idx; | ||
460 | rc = 0; | ||
461 | /* | ||
462 | * Loop backwards, so that the first hypercall has the largest | ||
463 | * index, ensuring that the table will grow only once. | ||
464 | */ | ||
465 | do { | ||
466 | xatp.domid = DOMID_SELF; | ||
467 | xatp.idx = i; | ||
468 | xatp.space = XENMAPSPACE_grant_table; | ||
469 | xatp.gpfn = (xen_hvm_resume_frames >> PAGE_SHIFT) + i; | ||
470 | rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp); | ||
471 | if (rc != 0) { | ||
472 | printk(KERN_WARNING | ||
473 | "grant table add_to_physmap failed, err=%d\n", rc); | ||
474 | break; | ||
475 | } | ||
476 | } while (i-- > start_idx); | ||
477 | |||
478 | return rc; | ||
479 | } | ||
480 | |||
452 | frames = kmalloc(nr_gframes * sizeof(unsigned long), GFP_ATOMIC); | 481 | frames = kmalloc(nr_gframes * sizeof(unsigned long), GFP_ATOMIC); |
453 | if (!frames) | 482 | if (!frames) |
454 | return -ENOMEM; | 483 | return -ENOMEM; |
@@ -465,7 +494,7 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx) | |||
465 | 494 | ||
466 | BUG_ON(rc || setup.status); | 495 | BUG_ON(rc || setup.status); |
467 | 496 | ||
468 | rc = arch_gnttab_map_shared(frames, nr_gframes, max_nr_grant_frames(), | 497 | rc = arch_gnttab_map_shared(frames, nr_gframes, gnttab_max_grant_frames(), |
469 | &shared); | 498 | &shared); |
470 | BUG_ON(rc); | 499 | BUG_ON(rc); |
471 | 500 | ||
@@ -476,9 +505,27 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx) | |||
476 | 505 | ||
477 | int gnttab_resume(void) | 506 | int gnttab_resume(void) |
478 | { | 507 | { |
479 | if (max_nr_grant_frames() < nr_grant_frames) | 508 | unsigned int max_nr_gframes; |
509 | |||
510 | max_nr_gframes = gnttab_max_grant_frames(); | ||
511 | if (max_nr_gframes < nr_grant_frames) | ||
480 | return -ENOSYS; | 512 | return -ENOSYS; |
481 | return gnttab_map(0, nr_grant_frames - 1); | 513 | |
514 | if (xen_pv_domain()) | ||
515 | return gnttab_map(0, nr_grant_frames - 1); | ||
516 | |||
517 | if (!shared) { | ||
518 | shared = ioremap(xen_hvm_resume_frames, PAGE_SIZE * max_nr_gframes); | ||
519 | if (shared == NULL) { | ||
520 | printk(KERN_WARNING | ||
521 | "Failed to ioremap gnttab share frames!"); | ||
522 | return -ENOMEM; | ||
523 | } | ||
524 | } | ||
525 | |||
526 | gnttab_map(0, nr_grant_frames - 1); | ||
527 | |||
528 | return 0; | ||
482 | } | 529 | } |
483 | 530 | ||
484 | int gnttab_suspend(void) | 531 | int gnttab_suspend(void) |
@@ -495,7 +542,7 @@ static int gnttab_expand(unsigned int req_entries) | |||
495 | cur = nr_grant_frames; | 542 | cur = nr_grant_frames; |
496 | extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) / | 543 | extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) / |
497 | GREFS_PER_GRANT_FRAME); | 544 | GREFS_PER_GRANT_FRAME); |
498 | if (cur + extra > max_nr_grant_frames()) | 545 | if (cur + extra > gnttab_max_grant_frames()) |
499 | return -ENOSPC; | 546 | return -ENOSPC; |
500 | 547 | ||
501 | rc = gnttab_map(cur, cur + extra - 1); | 548 | rc = gnttab_map(cur, cur + extra - 1); |
@@ -505,15 +552,12 @@ static int gnttab_expand(unsigned int req_entries) | |||
505 | return rc; | 552 | return rc; |
506 | } | 553 | } |
507 | 554 | ||
508 | static int __devinit gnttab_init(void) | 555 | int gnttab_init(void) |
509 | { | 556 | { |
510 | int i; | 557 | int i; |
511 | unsigned int max_nr_glist_frames, nr_glist_frames; | 558 | unsigned int max_nr_glist_frames, nr_glist_frames; |
512 | unsigned int nr_init_grefs; | 559 | unsigned int nr_init_grefs; |
513 | 560 | ||
514 | if (!xen_domain()) | ||
515 | return -ENODEV; | ||
516 | |||
517 | nr_grant_frames = 1; | 561 | nr_grant_frames = 1; |
518 | boot_max_nr_grant_frames = __max_nr_grant_frames(); | 562 | boot_max_nr_grant_frames = __max_nr_grant_frames(); |
519 | 563 | ||
@@ -556,5 +600,18 @@ static int __devinit gnttab_init(void) | |||
556 | kfree(gnttab_list); | 600 | kfree(gnttab_list); |
557 | return -ENOMEM; | 601 | return -ENOMEM; |
558 | } | 602 | } |
603 | EXPORT_SYMBOL_GPL(gnttab_init); | ||
604 | |||
605 | static int __devinit __gnttab_init(void) | ||
606 | { | ||
607 | /* Delay grant-table initialization in the PV on HVM case */ | ||
608 | if (xen_hvm_domain()) | ||
609 | return 0; | ||
610 | |||
611 | if (!xen_pv_domain()) | ||
612 | return -ENODEV; | ||
613 | |||
614 | return gnttab_init(); | ||
615 | } | ||
559 | 616 | ||
560 | core_initcall(gnttab_init); | 617 | core_initcall(__gnttab_init); |