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); |
