aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen/xenbus/xenbus_client.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/xen/xenbus/xenbus_client.c')
-rw-r--r--drivers/xen/xenbus/xenbus_client.c130
1 files changed, 67 insertions, 63 deletions
diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c
index 82a8866758ee..a1c17000129b 100644
--- a/drivers/xen/xenbus/xenbus_client.c
+++ b/drivers/xen/xenbus/xenbus_client.c
@@ -519,64 +519,6 @@ static int __xenbus_map_ring(struct xenbus_device *dev,
519 return err; 519 return err;
520} 520}
521 521
522static int xenbus_map_ring_valloc_pv(struct xenbus_device *dev,
523 grant_ref_t *gnt_refs,
524 unsigned int nr_grefs,
525 void **vaddr)
526{
527 struct xenbus_map_node *node;
528 struct vm_struct *area;
529 pte_t *ptes[XENBUS_MAX_RING_GRANTS];
530 phys_addr_t phys_addrs[XENBUS_MAX_RING_GRANTS];
531 int err = GNTST_okay;
532 int i;
533 bool leaked;
534
535 *vaddr = NULL;
536
537 if (nr_grefs > XENBUS_MAX_RING_GRANTS)
538 return -EINVAL;
539
540 node = kzalloc(sizeof(*node), GFP_KERNEL);
541 if (!node)
542 return -ENOMEM;
543
544 area = alloc_vm_area(XEN_PAGE_SIZE * nr_grefs, ptes);
545 if (!area) {
546 kfree(node);
547 return -ENOMEM;
548 }
549
550 for (i = 0; i < nr_grefs; i++)
551 phys_addrs[i] = arbitrary_virt_to_machine(ptes[i]).maddr;
552
553 err = __xenbus_map_ring(dev, gnt_refs, nr_grefs, node->handles,
554 phys_addrs,
555 GNTMAP_host_map | GNTMAP_contains_pte,
556 &leaked);
557 if (err)
558 goto failed;
559
560 node->nr_handles = nr_grefs;
561 node->pv.area = area;
562
563 spin_lock(&xenbus_valloc_lock);
564 list_add(&node->next, &xenbus_valloc_pages);
565 spin_unlock(&xenbus_valloc_lock);
566
567 *vaddr = area->addr;
568 return 0;
569
570failed:
571 if (!leaked)
572 free_vm_area(area);
573 else
574 pr_alert("leaking VM area %p size %u page(s)", area, nr_grefs);
575
576 kfree(node);
577 return err;
578}
579
580struct map_ring_valloc_hvm 522struct map_ring_valloc_hvm
581{ 523{
582 unsigned int idx; 524 unsigned int idx;
@@ -725,6 +667,65 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr)
725} 667}
726EXPORT_SYMBOL_GPL(xenbus_unmap_ring_vfree); 668EXPORT_SYMBOL_GPL(xenbus_unmap_ring_vfree);
727 669
670#ifdef CONFIG_XEN_PV
671static int xenbus_map_ring_valloc_pv(struct xenbus_device *dev,
672 grant_ref_t *gnt_refs,
673 unsigned int nr_grefs,
674 void **vaddr)
675{
676 struct xenbus_map_node *node;
677 struct vm_struct *area;
678 pte_t *ptes[XENBUS_MAX_RING_GRANTS];
679 phys_addr_t phys_addrs[XENBUS_MAX_RING_GRANTS];
680 int err = GNTST_okay;
681 int i;
682 bool leaked;
683
684 *vaddr = NULL;
685
686 if (nr_grefs > XENBUS_MAX_RING_GRANTS)
687 return -EINVAL;
688
689 node = kzalloc(sizeof(*node), GFP_KERNEL);
690 if (!node)
691 return -ENOMEM;
692
693 area = alloc_vm_area(XEN_PAGE_SIZE * nr_grefs, ptes);
694 if (!area) {
695 kfree(node);
696 return -ENOMEM;
697 }
698
699 for (i = 0; i < nr_grefs; i++)
700 phys_addrs[i] = arbitrary_virt_to_machine(ptes[i]).maddr;
701
702 err = __xenbus_map_ring(dev, gnt_refs, nr_grefs, node->handles,
703 phys_addrs,
704 GNTMAP_host_map | GNTMAP_contains_pte,
705 &leaked);
706 if (err)
707 goto failed;
708
709 node->nr_handles = nr_grefs;
710 node->pv.area = area;
711
712 spin_lock(&xenbus_valloc_lock);
713 list_add(&node->next, &xenbus_valloc_pages);
714 spin_unlock(&xenbus_valloc_lock);
715
716 *vaddr = area->addr;
717 return 0;
718
719failed:
720 if (!leaked)
721 free_vm_area(area);
722 else
723 pr_alert("leaking VM area %p size %u page(s)", area, nr_grefs);
724
725 kfree(node);
726 return err;
727}
728
728static int xenbus_unmap_ring_vfree_pv(struct xenbus_device *dev, void *vaddr) 729static int xenbus_unmap_ring_vfree_pv(struct xenbus_device *dev, void *vaddr)
729{ 730{
730 struct xenbus_map_node *node; 731 struct xenbus_map_node *node;
@@ -788,6 +789,12 @@ static int xenbus_unmap_ring_vfree_pv(struct xenbus_device *dev, void *vaddr)
788 return err; 789 return err;
789} 790}
790 791
792static const struct xenbus_ring_ops ring_ops_pv = {
793 .map = xenbus_map_ring_valloc_pv,
794 .unmap = xenbus_unmap_ring_vfree_pv,
795};
796#endif
797
791struct unmap_ring_vfree_hvm 798struct unmap_ring_vfree_hvm
792{ 799{
793 unsigned int idx; 800 unsigned int idx;
@@ -916,11 +923,6 @@ enum xenbus_state xenbus_read_driver_state(const char *path)
916} 923}
917EXPORT_SYMBOL_GPL(xenbus_read_driver_state); 924EXPORT_SYMBOL_GPL(xenbus_read_driver_state);
918 925
919static const struct xenbus_ring_ops ring_ops_pv = {
920 .map = xenbus_map_ring_valloc_pv,
921 .unmap = xenbus_unmap_ring_vfree_pv,
922};
923
924static const struct xenbus_ring_ops ring_ops_hvm = { 926static const struct xenbus_ring_ops ring_ops_hvm = {
925 .map = xenbus_map_ring_valloc_hvm, 927 .map = xenbus_map_ring_valloc_hvm,
926 .unmap = xenbus_unmap_ring_vfree_hvm, 928 .unmap = xenbus_unmap_ring_vfree_hvm,
@@ -928,8 +930,10 @@ static const struct xenbus_ring_ops ring_ops_hvm = {
928 930
929void __init xenbus_ring_ops_init(void) 931void __init xenbus_ring_ops_init(void)
930{ 932{
933#ifdef CONFIG_XEN_PV
931 if (!xen_feature(XENFEAT_auto_translated_physmap)) 934 if (!xen_feature(XENFEAT_auto_translated_physmap))
932 ring_ops = &ring_ops_pv; 935 ring_ops = &ring_ops_pv;
933 else 936 else
937#endif
934 ring_ops = &ring_ops_hvm; 938 ring_ops = &ring_ops_hvm;
935} 939}