diff options
-rw-r--r-- | arch/x86/include/asm/xen/page.h | 5 | ||||
-rw-r--r-- | arch/x86/include/asm/xen/pci.h | 16 | ||||
-rw-r--r-- | arch/x86/pci/xen.c | 96 | ||||
-rw-r--r-- | arch/x86/xen/p2m.c | 13 | ||||
-rw-r--r-- | drivers/xen/events.c | 39 | ||||
-rw-r--r-- | drivers/xen/gntalloc.c | 14 | ||||
-rw-r--r-- | drivers/xen/gntdev.c | 16 | ||||
-rw-r--r-- | drivers/xen/grant-table.c | 31 | ||||
-rw-r--r-- | include/xen/events.h | 9 |
9 files changed, 208 insertions, 31 deletions
diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h index c61934fbf22a..64a619d47d34 100644 --- a/arch/x86/include/asm/xen/page.h +++ b/arch/x86/include/asm/xen/page.h | |||
@@ -47,8 +47,9 @@ extern bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn); | |||
47 | extern unsigned long set_phys_range_identity(unsigned long pfn_s, | 47 | extern unsigned long set_phys_range_identity(unsigned long pfn_s, |
48 | unsigned long pfn_e); | 48 | unsigned long pfn_e); |
49 | 49 | ||
50 | extern int m2p_add_override(unsigned long mfn, struct page *page); | 50 | extern int m2p_add_override(unsigned long mfn, struct page *page, |
51 | extern int m2p_remove_override(struct page *page); | 51 | bool clear_pte); |
52 | extern int m2p_remove_override(struct page *page, bool clear_pte); | ||
52 | extern struct page *m2p_find_override(unsigned long mfn); | 53 | extern struct page *m2p_find_override(unsigned long mfn); |
53 | extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn); | 54 | extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn); |
54 | 55 | ||
diff --git a/arch/x86/include/asm/xen/pci.h b/arch/x86/include/asm/xen/pci.h index aa8620989162..4fbda9a3f339 100644 --- a/arch/x86/include/asm/xen/pci.h +++ b/arch/x86/include/asm/xen/pci.h | |||
@@ -15,10 +15,26 @@ static inline int pci_xen_hvm_init(void) | |||
15 | #endif | 15 | #endif |
16 | #if defined(CONFIG_XEN_DOM0) | 16 | #if defined(CONFIG_XEN_DOM0) |
17 | void __init xen_setup_pirqs(void); | 17 | void __init xen_setup_pirqs(void); |
18 | int xen_find_device_domain_owner(struct pci_dev *dev); | ||
19 | int xen_register_device_domain_owner(struct pci_dev *dev, uint16_t domain); | ||
20 | int xen_unregister_device_domain_owner(struct pci_dev *dev); | ||
18 | #else | 21 | #else |
19 | static inline void __init xen_setup_pirqs(void) | 22 | static inline void __init xen_setup_pirqs(void) |
20 | { | 23 | { |
21 | } | 24 | } |
25 | static inline int xen_find_device_domain_owner(struct pci_dev *dev) | ||
26 | { | ||
27 | return -1; | ||
28 | } | ||
29 | static inline int xen_register_device_domain_owner(struct pci_dev *dev, | ||
30 | uint16_t domain) | ||
31 | { | ||
32 | return -1; | ||
33 | } | ||
34 | static inline int xen_unregister_device_domain_owner(struct pci_dev *dev) | ||
35 | { | ||
36 | return -1; | ||
37 | } | ||
22 | #endif | 38 | #endif |
23 | 39 | ||
24 | #if defined(CONFIG_PCI_MSI) | 40 | #if defined(CONFIG_PCI_MSI) |
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index e37b407a0ee8..8214724ce54d 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c | |||
@@ -108,7 +108,8 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
108 | } | 108 | } |
109 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq, 0, | 109 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq, 0, |
110 | (type == PCI_CAP_ID_MSIX) ? | 110 | (type == PCI_CAP_ID_MSIX) ? |
111 | "msi-x" : "msi"); | 111 | "msi-x" : "msi", |
112 | DOMID_SELF); | ||
112 | if (irq < 0) | 113 | if (irq < 0) |
113 | goto error; | 114 | goto error; |
114 | dev_dbg(&dev->dev, | 115 | dev_dbg(&dev->dev, |
@@ -148,7 +149,8 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
148 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], 0, | 149 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], 0, |
149 | (type == PCI_CAP_ID_MSIX) ? | 150 | (type == PCI_CAP_ID_MSIX) ? |
150 | "pcifront-msi-x" : | 151 | "pcifront-msi-x" : |
151 | "pcifront-msi"); | 152 | "pcifront-msi", |
153 | DOMID_SELF); | ||
152 | if (irq < 0) | 154 | if (irq < 0) |
153 | goto free; | 155 | goto free; |
154 | i++; | 156 | i++; |
@@ -190,9 +192,16 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
190 | 192 | ||
191 | list_for_each_entry(msidesc, &dev->msi_list, list) { | 193 | list_for_each_entry(msidesc, &dev->msi_list, list) { |
192 | struct physdev_map_pirq map_irq; | 194 | struct physdev_map_pirq map_irq; |
195 | domid_t domid; | ||
196 | |||
197 | domid = ret = xen_find_device_domain_owner(dev); | ||
198 | /* N.B. Casting int's -ENODEV to uint16_t results in 0xFFED, | ||
199 | * hence check ret value for < 0. */ | ||
200 | if (ret < 0) | ||
201 | domid = DOMID_SELF; | ||
193 | 202 | ||
194 | memset(&map_irq, 0, sizeof(map_irq)); | 203 | memset(&map_irq, 0, sizeof(map_irq)); |
195 | map_irq.domid = DOMID_SELF; | 204 | map_irq.domid = domid; |
196 | map_irq.type = MAP_PIRQ_TYPE_MSI; | 205 | map_irq.type = MAP_PIRQ_TYPE_MSI; |
197 | map_irq.index = -1; | 206 | map_irq.index = -1; |
198 | map_irq.pirq = -1; | 207 | map_irq.pirq = -1; |
@@ -215,14 +224,16 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
215 | 224 | ||
216 | ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); | 225 | ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); |
217 | if (ret) { | 226 | if (ret) { |
218 | dev_warn(&dev->dev, "xen map irq failed %d\n", ret); | 227 | dev_warn(&dev->dev, "xen map irq failed %d for %d domain\n", |
228 | ret, domid); | ||
219 | goto out; | 229 | goto out; |
220 | } | 230 | } |
221 | 231 | ||
222 | ret = xen_bind_pirq_msi_to_irq(dev, msidesc, | 232 | ret = xen_bind_pirq_msi_to_irq(dev, msidesc, |
223 | map_irq.pirq, map_irq.index, | 233 | map_irq.pirq, map_irq.index, |
224 | (type == PCI_CAP_ID_MSIX) ? | 234 | (type == PCI_CAP_ID_MSIX) ? |
225 | "msi-x" : "msi"); | 235 | "msi-x" : "msi", |
236 | domid); | ||
226 | if (ret < 0) | 237 | if (ret < 0) |
227 | goto out; | 238 | goto out; |
228 | } | 239 | } |
@@ -461,3 +472,78 @@ void __init xen_setup_pirqs(void) | |||
461 | } | 472 | } |
462 | } | 473 | } |
463 | #endif | 474 | #endif |
475 | |||
476 | #ifdef CONFIG_XEN_DOM0 | ||
477 | struct xen_device_domain_owner { | ||
478 | domid_t domain; | ||
479 | struct pci_dev *dev; | ||
480 | struct list_head list; | ||
481 | }; | ||
482 | |||
483 | static DEFINE_SPINLOCK(dev_domain_list_spinlock); | ||
484 | static struct list_head dev_domain_list = LIST_HEAD_INIT(dev_domain_list); | ||
485 | |||
486 | static struct xen_device_domain_owner *find_device(struct pci_dev *dev) | ||
487 | { | ||
488 | struct xen_device_domain_owner *owner; | ||
489 | |||
490 | list_for_each_entry(owner, &dev_domain_list, list) { | ||
491 | if (owner->dev == dev) | ||
492 | return owner; | ||
493 | } | ||
494 | return NULL; | ||
495 | } | ||
496 | |||
497 | int xen_find_device_domain_owner(struct pci_dev *dev) | ||
498 | { | ||
499 | struct xen_device_domain_owner *owner; | ||
500 | int domain = -ENODEV; | ||
501 | |||
502 | spin_lock(&dev_domain_list_spinlock); | ||
503 | owner = find_device(dev); | ||
504 | if (owner) | ||
505 | domain = owner->domain; | ||
506 | spin_unlock(&dev_domain_list_spinlock); | ||
507 | return domain; | ||
508 | } | ||
509 | EXPORT_SYMBOL_GPL(xen_find_device_domain_owner); | ||
510 | |||
511 | int xen_register_device_domain_owner(struct pci_dev *dev, uint16_t domain) | ||
512 | { | ||
513 | struct xen_device_domain_owner *owner; | ||
514 | |||
515 | owner = kzalloc(sizeof(struct xen_device_domain_owner), GFP_KERNEL); | ||
516 | if (!owner) | ||
517 | return -ENODEV; | ||
518 | |||
519 | spin_lock(&dev_domain_list_spinlock); | ||
520 | if (find_device(dev)) { | ||
521 | spin_unlock(&dev_domain_list_spinlock); | ||
522 | kfree(owner); | ||
523 | return -EEXIST; | ||
524 | } | ||
525 | owner->domain = domain; | ||
526 | owner->dev = dev; | ||
527 | list_add_tail(&owner->list, &dev_domain_list); | ||
528 | spin_unlock(&dev_domain_list_spinlock); | ||
529 | return 0; | ||
530 | } | ||
531 | EXPORT_SYMBOL_GPL(xen_register_device_domain_owner); | ||
532 | |||
533 | int xen_unregister_device_domain_owner(struct pci_dev *dev) | ||
534 | { | ||
535 | struct xen_device_domain_owner *owner; | ||
536 | |||
537 | spin_lock(&dev_domain_list_spinlock); | ||
538 | owner = find_device(dev); | ||
539 | if (!owner) { | ||
540 | spin_unlock(&dev_domain_list_spinlock); | ||
541 | return -ENODEV; | ||
542 | } | ||
543 | list_del(&owner->list); | ||
544 | spin_unlock(&dev_domain_list_spinlock); | ||
545 | kfree(owner); | ||
546 | return 0; | ||
547 | } | ||
548 | EXPORT_SYMBOL_GPL(xen_unregister_device_domain_owner); | ||
549 | #endif | ||
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index 141eb0de8b06..c851397e657c 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c | |||
@@ -650,7 +650,7 @@ static unsigned long mfn_hash(unsigned long mfn) | |||
650 | } | 650 | } |
651 | 651 | ||
652 | /* Add an MFN override for a particular page */ | 652 | /* Add an MFN override for a particular page */ |
653 | int m2p_add_override(unsigned long mfn, struct page *page) | 653 | int m2p_add_override(unsigned long mfn, struct page *page, bool clear_pte) |
654 | { | 654 | { |
655 | unsigned long flags; | 655 | unsigned long flags; |
656 | unsigned long pfn; | 656 | unsigned long pfn; |
@@ -662,7 +662,6 @@ int m2p_add_override(unsigned long mfn, struct page *page) | |||
662 | if (!PageHighMem(page)) { | 662 | if (!PageHighMem(page)) { |
663 | address = (unsigned long)__va(pfn << PAGE_SHIFT); | 663 | address = (unsigned long)__va(pfn << PAGE_SHIFT); |
664 | ptep = lookup_address(address, &level); | 664 | ptep = lookup_address(address, &level); |
665 | |||
666 | if (WARN(ptep == NULL || level != PG_LEVEL_4K, | 665 | if (WARN(ptep == NULL || level != PG_LEVEL_4K, |
667 | "m2p_add_override: pfn %lx not mapped", pfn)) | 666 | "m2p_add_override: pfn %lx not mapped", pfn)) |
668 | return -EINVAL; | 667 | return -EINVAL; |
@@ -674,18 +673,17 @@ int m2p_add_override(unsigned long mfn, struct page *page) | |||
674 | if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn)))) | 673 | if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn)))) |
675 | return -ENOMEM; | 674 | return -ENOMEM; |
676 | 675 | ||
677 | if (!PageHighMem(page)) | 676 | if (clear_pte && !PageHighMem(page)) |
678 | /* Just zap old mapping for now */ | 677 | /* Just zap old mapping for now */ |
679 | pte_clear(&init_mm, address, ptep); | 678 | pte_clear(&init_mm, address, ptep); |
680 | |||
681 | spin_lock_irqsave(&m2p_override_lock, flags); | 679 | spin_lock_irqsave(&m2p_override_lock, flags); |
682 | list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]); | 680 | list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]); |
683 | spin_unlock_irqrestore(&m2p_override_lock, flags); | 681 | spin_unlock_irqrestore(&m2p_override_lock, flags); |
684 | 682 | ||
685 | return 0; | 683 | return 0; |
686 | } | 684 | } |
687 | 685 | EXPORT_SYMBOL_GPL(m2p_add_override); | |
688 | int m2p_remove_override(struct page *page) | 686 | int m2p_remove_override(struct page *page, bool clear_pte) |
689 | { | 687 | { |
690 | unsigned long flags; | 688 | unsigned long flags; |
691 | unsigned long mfn; | 689 | unsigned long mfn; |
@@ -713,7 +711,7 @@ int m2p_remove_override(struct page *page) | |||
713 | spin_unlock_irqrestore(&m2p_override_lock, flags); | 711 | spin_unlock_irqrestore(&m2p_override_lock, flags); |
714 | set_phys_to_machine(pfn, page->index); | 712 | set_phys_to_machine(pfn, page->index); |
715 | 713 | ||
716 | if (!PageHighMem(page)) | 714 | if (clear_pte && !PageHighMem(page)) |
717 | set_pte_at(&init_mm, address, ptep, | 715 | set_pte_at(&init_mm, address, ptep, |
718 | pfn_pte(pfn, PAGE_KERNEL)); | 716 | pfn_pte(pfn, PAGE_KERNEL)); |
719 | /* No tlb flush necessary because the caller already | 717 | /* No tlb flush necessary because the caller already |
@@ -721,6 +719,7 @@ int m2p_remove_override(struct page *page) | |||
721 | 719 | ||
722 | return 0; | 720 | return 0; |
723 | } | 721 | } |
722 | EXPORT_SYMBOL_GPL(m2p_remove_override); | ||
724 | 723 | ||
725 | struct page *m2p_find_override(unsigned long mfn) | 724 | struct page *m2p_find_override(unsigned long mfn) |
726 | { | 725 | { |
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 33167b43ac7e..35e02a10110b 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
@@ -101,6 +101,7 @@ struct irq_info | |||
101 | unsigned short gsi; | 101 | unsigned short gsi; |
102 | unsigned char vector; | 102 | unsigned char vector; |
103 | unsigned char flags; | 103 | unsigned char flags; |
104 | uint16_t domid; | ||
104 | } pirq; | 105 | } pirq; |
105 | } u; | 106 | } u; |
106 | }; | 107 | }; |
@@ -184,6 +185,7 @@ static void xen_irq_info_pirq_init(unsigned irq, | |||
184 | unsigned short pirq, | 185 | unsigned short pirq, |
185 | unsigned short gsi, | 186 | unsigned short gsi, |
186 | unsigned short vector, | 187 | unsigned short vector, |
188 | uint16_t domid, | ||
187 | unsigned char flags) | 189 | unsigned char flags) |
188 | { | 190 | { |
189 | struct irq_info *info = info_for_irq(irq); | 191 | struct irq_info *info = info_for_irq(irq); |
@@ -193,6 +195,7 @@ static void xen_irq_info_pirq_init(unsigned irq, | |||
193 | info->u.pirq.pirq = pirq; | 195 | info->u.pirq.pirq = pirq; |
194 | info->u.pirq.gsi = gsi; | 196 | info->u.pirq.gsi = gsi; |
195 | info->u.pirq.vector = vector; | 197 | info->u.pirq.vector = vector; |
198 | info->u.pirq.domid = domid; | ||
196 | info->u.pirq.flags = flags; | 199 | info->u.pirq.flags = flags; |
197 | } | 200 | } |
198 | 201 | ||
@@ -655,7 +658,7 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi, | |||
655 | goto out; | 658 | goto out; |
656 | } | 659 | } |
657 | 660 | ||
658 | xen_irq_info_pirq_init(irq, 0, pirq, gsi, irq_op.vector, | 661 | xen_irq_info_pirq_init(irq, 0, pirq, gsi, irq_op.vector, DOMID_SELF, |
659 | shareable ? PIRQ_SHAREABLE : 0); | 662 | shareable ? PIRQ_SHAREABLE : 0); |
660 | 663 | ||
661 | out: | 664 | out: |
@@ -680,7 +683,8 @@ int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc) | |||
680 | } | 683 | } |
681 | 684 | ||
682 | int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, | 685 | int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, |
683 | int pirq, int vector, const char *name) | 686 | int pirq, int vector, const char *name, |
687 | domid_t domid) | ||
684 | { | 688 | { |
685 | int irq, ret; | 689 | int irq, ret; |
686 | 690 | ||
@@ -693,7 +697,7 @@ int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, | |||
693 | irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_level_irq, | 697 | irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_level_irq, |
694 | name); | 698 | name); |
695 | 699 | ||
696 | xen_irq_info_pirq_init(irq, 0, pirq, 0, vector, 0); | 700 | xen_irq_info_pirq_init(irq, 0, pirq, 0, vector, domid, 0); |
697 | ret = irq_set_msi_desc(irq, msidesc); | 701 | ret = irq_set_msi_desc(irq, msidesc); |
698 | if (ret < 0) | 702 | if (ret < 0) |
699 | goto error_irq; | 703 | goto error_irq; |
@@ -722,9 +726,16 @@ int xen_destroy_irq(int irq) | |||
722 | 726 | ||
723 | if (xen_initial_domain()) { | 727 | if (xen_initial_domain()) { |
724 | unmap_irq.pirq = info->u.pirq.pirq; | 728 | unmap_irq.pirq = info->u.pirq.pirq; |
725 | unmap_irq.domid = DOMID_SELF; | 729 | unmap_irq.domid = info->u.pirq.domid; |
726 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap_irq); | 730 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap_irq); |
727 | if (rc) { | 731 | /* If another domain quits without making the pci_disable_msix |
732 | * call, the Xen hypervisor takes care of freeing the PIRQs | ||
733 | * (free_domain_pirqs). | ||
734 | */ | ||
735 | if ((rc == -ESRCH && info->u.pirq.domid != DOMID_SELF)) | ||
736 | printk(KERN_INFO "domain %d does not have %d anymore\n", | ||
737 | info->u.pirq.domid, info->u.pirq.pirq); | ||
738 | else if (rc) { | ||
728 | printk(KERN_WARNING "unmap irq failed %d\n", rc); | 739 | printk(KERN_WARNING "unmap irq failed %d\n", rc); |
729 | goto out; | 740 | goto out; |
730 | } | 741 | } |
@@ -759,6 +770,12 @@ out: | |||
759 | return irq; | 770 | return irq; |
760 | } | 771 | } |
761 | 772 | ||
773 | |||
774 | int xen_pirq_from_irq(unsigned irq) | ||
775 | { | ||
776 | return pirq_from_irq(irq); | ||
777 | } | ||
778 | EXPORT_SYMBOL_GPL(xen_pirq_from_irq); | ||
762 | int bind_evtchn_to_irq(unsigned int evtchn) | 779 | int bind_evtchn_to_irq(unsigned int evtchn) |
763 | { | 780 | { |
764 | int irq; | 781 | int irq; |
@@ -1502,6 +1519,18 @@ void xen_poll_irq(int irq) | |||
1502 | xen_poll_irq_timeout(irq, 0 /* no timeout */); | 1519 | xen_poll_irq_timeout(irq, 0 /* no timeout */); |
1503 | } | 1520 | } |
1504 | 1521 | ||
1522 | /* Check whether the IRQ line is shared with other guests. */ | ||
1523 | int xen_test_irq_shared(int irq) | ||
1524 | { | ||
1525 | struct irq_info *info = info_for_irq(irq); | ||
1526 | struct physdev_irq_status_query irq_status = { .irq = info->u.pirq.pirq }; | ||
1527 | |||
1528 | if (HYPERVISOR_physdev_op(PHYSDEVOP_irq_status_query, &irq_status)) | ||
1529 | return 0; | ||
1530 | return !(irq_status.flags & XENIRQSTAT_shared); | ||
1531 | } | ||
1532 | EXPORT_SYMBOL_GPL(xen_test_irq_shared); | ||
1533 | |||
1505 | void xen_irq_resume(void) | 1534 | void xen_irq_resume(void) |
1506 | { | 1535 | { |
1507 | unsigned int cpu, evtchn; | 1536 | unsigned int cpu, evtchn; |
diff --git a/drivers/xen/gntalloc.c b/drivers/xen/gntalloc.c index a7ffdfe19fc9..f6832f46aea4 100644 --- a/drivers/xen/gntalloc.c +++ b/drivers/xen/gntalloc.c | |||
@@ -427,6 +427,17 @@ static long gntalloc_ioctl(struct file *filp, unsigned int cmd, | |||
427 | return 0; | 427 | return 0; |
428 | } | 428 | } |
429 | 429 | ||
430 | static void gntalloc_vma_open(struct vm_area_struct *vma) | ||
431 | { | ||
432 | struct gntalloc_gref *gref = vma->vm_private_data; | ||
433 | if (!gref) | ||
434 | return; | ||
435 | |||
436 | spin_lock(&gref_lock); | ||
437 | gref->users++; | ||
438 | spin_unlock(&gref_lock); | ||
439 | } | ||
440 | |||
430 | static void gntalloc_vma_close(struct vm_area_struct *vma) | 441 | static void gntalloc_vma_close(struct vm_area_struct *vma) |
431 | { | 442 | { |
432 | struct gntalloc_gref *gref = vma->vm_private_data; | 443 | struct gntalloc_gref *gref = vma->vm_private_data; |
@@ -441,6 +452,7 @@ static void gntalloc_vma_close(struct vm_area_struct *vma) | |||
441 | } | 452 | } |
442 | 453 | ||
443 | static struct vm_operations_struct gntalloc_vmops = { | 454 | static struct vm_operations_struct gntalloc_vmops = { |
455 | .open = gntalloc_vma_open, | ||
444 | .close = gntalloc_vma_close, | 456 | .close = gntalloc_vma_close, |
445 | }; | 457 | }; |
446 | 458 | ||
@@ -471,8 +483,6 @@ static int gntalloc_mmap(struct file *filp, struct vm_area_struct *vma) | |||
471 | vma->vm_private_data = gref; | 483 | vma->vm_private_data = gref; |
472 | 484 | ||
473 | vma->vm_flags |= VM_RESERVED; | 485 | vma->vm_flags |= VM_RESERVED; |
474 | vma->vm_flags |= VM_DONTCOPY; | ||
475 | vma->vm_flags |= VM_PFNMAP | VM_PFN_AT_MMAP; | ||
476 | 486 | ||
477 | vma->vm_ops = &gntalloc_vmops; | 487 | vma->vm_ops = &gntalloc_vmops; |
478 | 488 | ||
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index b0f9e8fb0052..f914b26cf0c2 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c | |||
@@ -330,17 +330,26 @@ static int unmap_grant_pages(struct grant_map *map, int offset, int pages) | |||
330 | 330 | ||
331 | /* ------------------------------------------------------------------ */ | 331 | /* ------------------------------------------------------------------ */ |
332 | 332 | ||
333 | static void gntdev_vma_open(struct vm_area_struct *vma) | ||
334 | { | ||
335 | struct grant_map *map = vma->vm_private_data; | ||
336 | |||
337 | pr_debug("gntdev_vma_open %p\n", vma); | ||
338 | atomic_inc(&map->users); | ||
339 | } | ||
340 | |||
333 | static void gntdev_vma_close(struct vm_area_struct *vma) | 341 | static void gntdev_vma_close(struct vm_area_struct *vma) |
334 | { | 342 | { |
335 | struct grant_map *map = vma->vm_private_data; | 343 | struct grant_map *map = vma->vm_private_data; |
336 | 344 | ||
337 | pr_debug("close %p\n", vma); | 345 | pr_debug("gntdev_vma_close %p\n", vma); |
338 | map->vma = NULL; | 346 | map->vma = NULL; |
339 | vma->vm_private_data = NULL; | 347 | vma->vm_private_data = NULL; |
340 | gntdev_put_map(map); | 348 | gntdev_put_map(map); |
341 | } | 349 | } |
342 | 350 | ||
343 | static struct vm_operations_struct gntdev_vmops = { | 351 | static struct vm_operations_struct gntdev_vmops = { |
352 | .open = gntdev_vma_open, | ||
344 | .close = gntdev_vma_close, | 353 | .close = gntdev_vma_close, |
345 | }; | 354 | }; |
346 | 355 | ||
@@ -652,7 +661,10 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma) | |||
652 | 661 | ||
653 | vma->vm_ops = &gntdev_vmops; | 662 | vma->vm_ops = &gntdev_vmops; |
654 | 663 | ||
655 | vma->vm_flags |= VM_RESERVED|VM_DONTCOPY|VM_DONTEXPAND|VM_PFNMAP; | 664 | vma->vm_flags |= VM_RESERVED|VM_DONTEXPAND; |
665 | |||
666 | if (use_ptemod) | ||
667 | vma->vm_flags |= VM_DONTCOPY|VM_PFNMAP; | ||
656 | 668 | ||
657 | vma->vm_private_data = map; | 669 | vma->vm_private_data = map; |
658 | 670 | ||
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 3745a318defc..fd725cde6ad1 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c | |||
@@ -466,13 +466,30 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, | |||
466 | if (map_ops[i].status) | 466 | if (map_ops[i].status) |
467 | continue; | 467 | continue; |
468 | 468 | ||
469 | /* m2p override only supported for GNTMAP_contains_pte mappings */ | 469 | if (map_ops[i].flags & GNTMAP_contains_pte) { |
470 | if (!(map_ops[i].flags & GNTMAP_contains_pte)) | 470 | pte = (pte_t *) (mfn_to_virt(PFN_DOWN(map_ops[i].host_addr)) + |
471 | continue; | ||
472 | pte = (pte_t *) (mfn_to_virt(PFN_DOWN(map_ops[i].host_addr)) + | ||
473 | (map_ops[i].host_addr & ~PAGE_MASK)); | 471 | (map_ops[i].host_addr & ~PAGE_MASK)); |
474 | mfn = pte_mfn(*pte); | 472 | mfn = pte_mfn(*pte); |
475 | ret = m2p_add_override(mfn, pages[i]); | 473 | } else { |
474 | /* If you really wanted to do this: | ||
475 | * mfn = PFN_DOWN(map_ops[i].dev_bus_addr); | ||
476 | * | ||
477 | * The reason we do not implement it is b/c on the | ||
478 | * unmap path (gnttab_unmap_refs) we have no means of | ||
479 | * checking whether the page is !GNTMAP_contains_pte. | ||
480 | * | ||
481 | * That is without some extra data-structure to carry | ||
482 | * the struct page, bool clear_pte, and list_head next | ||
483 | * tuples and deal with allocation/delallocation, etc. | ||
484 | * | ||
485 | * The users of this API set the GNTMAP_contains_pte | ||
486 | * flag so lets just return not supported until it | ||
487 | * becomes neccessary to implement. | ||
488 | */ | ||
489 | return -EOPNOTSUPP; | ||
490 | } | ||
491 | ret = m2p_add_override(mfn, pages[i], | ||
492 | map_ops[i].flags & GNTMAP_contains_pte); | ||
476 | if (ret) | 493 | if (ret) |
477 | return ret; | 494 | return ret; |
478 | } | 495 | } |
@@ -494,7 +511,7 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, | |||
494 | return ret; | 511 | return ret; |
495 | 512 | ||
496 | for (i = 0; i < count; i++) { | 513 | for (i = 0; i < count; i++) { |
497 | ret = m2p_remove_override(pages[i]); | 514 | ret = m2p_remove_override(pages[i], true /* clear the PTE */); |
498 | if (ret) | 515 | if (ret) |
499 | return ret; | 516 | return ret; |
500 | } | 517 | } |
diff --git a/include/xen/events.h b/include/xen/events.h index f1b87ad48ac7..9af21e19545a 100644 --- a/include/xen/events.h +++ b/include/xen/events.h | |||
@@ -85,7 +85,8 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi, | |||
85 | int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc); | 85 | int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc); |
86 | /* Bind an PSI pirq to an irq. */ | 86 | /* Bind an PSI pirq to an irq. */ |
87 | int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, | 87 | int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, |
88 | int pirq, int vector, const char *name); | 88 | int pirq, int vector, const char *name, |
89 | domid_t domid); | ||
89 | #endif | 90 | #endif |
90 | 91 | ||
91 | /* De-allocates the above mentioned physical interrupt. */ | 92 | /* De-allocates the above mentioned physical interrupt. */ |
@@ -94,4 +95,10 @@ int xen_destroy_irq(int irq); | |||
94 | /* Return irq from pirq */ | 95 | /* Return irq from pirq */ |
95 | int xen_irq_from_pirq(unsigned pirq); | 96 | int xen_irq_from_pirq(unsigned pirq); |
96 | 97 | ||
98 | /* Return the pirq allocated to the irq. */ | ||
99 | int xen_pirq_from_irq(unsigned irq); | ||
100 | |||
101 | /* Determine whether to ignore this IRQ if it is passed to a guest. */ | ||
102 | int xen_test_irq_shared(int irq); | ||
103 | |||
97 | #endif /* _XEN_EVENTS_H */ | 104 | #endif /* _XEN_EVENTS_H */ |