aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen/grant-table.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/xen/grant-table.c')
-rw-r--r--drivers/xen/grant-table.c77
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;
59static int gnttab_free_count; 61static int gnttab_free_count;
60static grant_ref_t gnttab_free_head; 62static grant_ref_t gnttab_free_head;
61static DEFINE_SPINLOCK(gnttab_list_lock); 63static DEFINE_SPINLOCK(gnttab_list_lock);
64unsigned long xen_hvm_resume_frames;
65EXPORT_SYMBOL_GPL(xen_hvm_resume_frames);
62 66
63static struct grant_entry *shared; 67static 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
436static inline unsigned int max_nr_grant_frames(void) 440unsigned 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}
448EXPORT_SYMBOL_GPL(gnttab_max_grant_frames);
444 449
445static int gnttab_map(unsigned int start_idx, unsigned int end_idx) 450static 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
477int gnttab_resume(void) 506int 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
484int gnttab_suspend(void) 531int 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
508static int __devinit gnttab_init(void) 555int 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}
603EXPORT_SYMBOL_GPL(gnttab_init);
604
605static 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
560core_initcall(gnttab_init); 617core_initcall(__gnttab_init);