diff options
| -rw-r--r-- | arch/arm/include/asm/xen/page.h | 15 | ||||
| -rw-r--r-- | arch/arm/xen/p2m.c | 32 | ||||
| -rw-r--r-- | arch/x86/include/asm/xen/page.h | 11 | ||||
| -rw-r--r-- | arch/x86/pci/xen.c | 29 | ||||
| -rw-r--r-- | arch/x86/xen/Kconfig | 5 | ||||
| -rw-r--r-- | arch/x86/xen/p2m.c | 121 | ||||
| -rw-r--r-- | drivers/xen/events/events_base.c | 83 | ||||
| -rw-r--r-- | drivers/xen/events/events_internal.h | 1 | ||||
| -rw-r--r-- | drivers/xen/grant-table.c | 73 | ||||
| -rw-r--r-- | drivers/xen/manage.c | 16 | ||||
| -rw-r--r-- | drivers/xen/pcpu.c | 1 | ||||
| -rw-r--r-- | drivers/xen/platform-pci.c | 2 | ||||
| -rw-r--r-- | drivers/xen/xen-acpi-processor.c | 15 | ||||
| -rw-r--r-- | drivers/xen/xen-pciback/pciback_ops.c | 3 | ||||
| -rw-r--r-- | drivers/xen/xen-selfballoon.c | 1 | ||||
| -rw-r--r-- | drivers/xen/xenbus/xenbus_client.c | 27 | ||||
| -rw-r--r-- | include/xen/events.h | 6 | ||||
| -rw-r--r-- | include/xen/interface/physdev.h | 10 | ||||
| -rw-r--r-- | include/xen/xen-ops.h | 4 | ||||
| -rw-r--r-- | include/xen/xenbus.h | 1 |
20 files changed, 265 insertions, 191 deletions
diff --git a/arch/arm/include/asm/xen/page.h b/arch/arm/include/asm/xen/page.h index e0965abacb7d..cf4f3e867395 100644 --- a/arch/arm/include/asm/xen/page.h +++ b/arch/arm/include/asm/xen/page.h | |||
| @@ -97,16 +97,13 @@ static inline pte_t *lookup_address(unsigned long address, unsigned int *level) | |||
| 97 | return NULL; | 97 | return NULL; |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | static inline int m2p_add_override(unsigned long mfn, struct page *page, | 100 | extern int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops, |
| 101 | struct gnttab_map_grant_ref *kmap_op) | 101 | struct gnttab_map_grant_ref *kmap_ops, |
| 102 | { | 102 | struct page **pages, unsigned int count); |
| 103 | return 0; | ||
| 104 | } | ||
| 105 | 103 | ||
| 106 | static inline int m2p_remove_override(struct page *page, bool clear_pte) | 104 | extern int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops, |
| 107 | { | 105 | struct gnttab_map_grant_ref *kmap_ops, |
| 108 | return 0; | 106 | struct page **pages, unsigned int count); |
| 109 | } | ||
| 110 | 107 | ||
| 111 | bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn); | 108 | bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn); |
| 112 | bool __set_phys_to_machine_multi(unsigned long pfn, unsigned long mfn, | 109 | bool __set_phys_to_machine_multi(unsigned long pfn, unsigned long mfn, |
diff --git a/arch/arm/xen/p2m.c b/arch/arm/xen/p2m.c index b31ee1b275b0..97baf4427817 100644 --- a/arch/arm/xen/p2m.c +++ b/arch/arm/xen/p2m.c | |||
| @@ -146,6 +146,38 @@ unsigned long __mfn_to_pfn(unsigned long mfn) | |||
| 146 | } | 146 | } |
| 147 | EXPORT_SYMBOL_GPL(__mfn_to_pfn); | 147 | EXPORT_SYMBOL_GPL(__mfn_to_pfn); |
| 148 | 148 | ||
| 149 | int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops, | ||
| 150 | struct gnttab_map_grant_ref *kmap_ops, | ||
| 151 | struct page **pages, unsigned int count) | ||
| 152 | { | ||
| 153 | int i; | ||
| 154 | |||
| 155 | for (i = 0; i < count; i++) { | ||
| 156 | if (map_ops[i].status) | ||
| 157 | continue; | ||
| 158 | set_phys_to_machine(map_ops[i].host_addr >> PAGE_SHIFT, | ||
| 159 | map_ops[i].dev_bus_addr >> PAGE_SHIFT); | ||
| 160 | } | ||
| 161 | |||
| 162 | return 0; | ||
| 163 | } | ||
| 164 | EXPORT_SYMBOL_GPL(set_foreign_p2m_mapping); | ||
| 165 | |||
| 166 | int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops, | ||
| 167 | struct gnttab_map_grant_ref *kmap_ops, | ||
| 168 | struct page **pages, unsigned int count) | ||
| 169 | { | ||
| 170 | int i; | ||
| 171 | |||
| 172 | for (i = 0; i < count; i++) { | ||
| 173 | set_phys_to_machine(unmap_ops[i].host_addr >> PAGE_SHIFT, | ||
| 174 | INVALID_P2M_ENTRY); | ||
| 175 | } | ||
| 176 | |||
| 177 | return 0; | ||
| 178 | } | ||
| 179 | EXPORT_SYMBOL_GPL(clear_foreign_p2m_mapping); | ||
| 180 | |||
| 149 | bool __set_phys_to_machine_multi(unsigned long pfn, | 181 | bool __set_phys_to_machine_multi(unsigned long pfn, |
| 150 | unsigned long mfn, unsigned long nr_pages) | 182 | unsigned long mfn, unsigned long nr_pages) |
| 151 | { | 183 | { |
diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h index 3e276eb23d1b..c949923a5668 100644 --- a/arch/x86/include/asm/xen/page.h +++ b/arch/x86/include/asm/xen/page.h | |||
| @@ -49,10 +49,17 @@ extern bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn); | |||
| 49 | extern unsigned long set_phys_range_identity(unsigned long pfn_s, | 49 | extern unsigned long set_phys_range_identity(unsigned long pfn_s, |
| 50 | unsigned long pfn_e); | 50 | unsigned long pfn_e); |
| 51 | 51 | ||
| 52 | extern int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops, | ||
| 53 | struct gnttab_map_grant_ref *kmap_ops, | ||
| 54 | struct page **pages, unsigned int count); | ||
| 52 | extern int m2p_add_override(unsigned long mfn, struct page *page, | 55 | extern int m2p_add_override(unsigned long mfn, struct page *page, |
| 53 | struct gnttab_map_grant_ref *kmap_op); | 56 | struct gnttab_map_grant_ref *kmap_op); |
| 57 | extern int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops, | ||
| 58 | struct gnttab_map_grant_ref *kmap_ops, | ||
| 59 | struct page **pages, unsigned int count); | ||
| 54 | extern int m2p_remove_override(struct page *page, | 60 | extern int m2p_remove_override(struct page *page, |
| 55 | struct gnttab_map_grant_ref *kmap_op); | 61 | struct gnttab_map_grant_ref *kmap_op, |
| 62 | unsigned long mfn); | ||
| 56 | extern struct page *m2p_find_override(unsigned long mfn); | 63 | extern struct page *m2p_find_override(unsigned long mfn); |
| 57 | extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn); | 64 | extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn); |
| 58 | 65 | ||
| @@ -121,7 +128,7 @@ static inline unsigned long mfn_to_pfn(unsigned long mfn) | |||
| 121 | pfn = m2p_find_override_pfn(mfn, ~0); | 128 | pfn = m2p_find_override_pfn(mfn, ~0); |
| 122 | } | 129 | } |
| 123 | 130 | ||
| 124 | /* | 131 | /* |
| 125 | * pfn is ~0 if there are no entries in the m2p for mfn or if the | 132 | * pfn is ~0 if there are no entries in the m2p for mfn or if the |
| 126 | * entry doesn't map back to the mfn and m2p_override doesn't have a | 133 | * entry doesn't map back to the mfn and m2p_override doesn't have a |
| 127 | * valid entry for it. | 134 | * valid entry for it. |
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 103e702ec5a7..905956f16465 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c | |||
| @@ -178,6 +178,7 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
| 178 | i = 0; | 178 | i = 0; |
| 179 | list_for_each_entry(msidesc, &dev->msi_list, list) { | 179 | list_for_each_entry(msidesc, &dev->msi_list, list) { |
| 180 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], | 180 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], |
| 181 | (type == PCI_CAP_ID_MSI) ? nvec : 1, | ||
| 181 | (type == PCI_CAP_ID_MSIX) ? | 182 | (type == PCI_CAP_ID_MSIX) ? |
| 182 | "pcifront-msi-x" : | 183 | "pcifront-msi-x" : |
| 183 | "pcifront-msi", | 184 | "pcifront-msi", |
| @@ -245,6 +246,7 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
| 245 | "xen: msi already bound to pirq=%d\n", pirq); | 246 | "xen: msi already bound to pirq=%d\n", pirq); |
| 246 | } | 247 | } |
| 247 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq, | 248 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq, |
| 249 | (type == PCI_CAP_ID_MSI) ? nvec : 1, | ||
| 248 | (type == PCI_CAP_ID_MSIX) ? | 250 | (type == PCI_CAP_ID_MSIX) ? |
| 249 | "msi-x" : "msi", | 251 | "msi-x" : "msi", |
| 250 | DOMID_SELF); | 252 | DOMID_SELF); |
| @@ -269,9 +271,6 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
| 269 | int ret = 0; | 271 | int ret = 0; |
| 270 | struct msi_desc *msidesc; | 272 | struct msi_desc *msidesc; |
| 271 | 273 | ||
| 272 | if (type == PCI_CAP_ID_MSI && nvec > 1) | ||
| 273 | return 1; | ||
| 274 | |||
| 275 | list_for_each_entry(msidesc, &dev->msi_list, list) { | 274 | list_for_each_entry(msidesc, &dev->msi_list, list) { |
| 276 | struct physdev_map_pirq map_irq; | 275 | struct physdev_map_pirq map_irq; |
| 277 | domid_t domid; | 276 | domid_t domid; |
| @@ -291,7 +290,10 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
| 291 | (pci_domain_nr(dev->bus) << 16); | 290 | (pci_domain_nr(dev->bus) << 16); |
| 292 | map_irq.devfn = dev->devfn; | 291 | map_irq.devfn = dev->devfn; |
| 293 | 292 | ||
| 294 | if (type == PCI_CAP_ID_MSIX) { | 293 | if (type == PCI_CAP_ID_MSI && nvec > 1) { |
| 294 | map_irq.type = MAP_PIRQ_TYPE_MULTI_MSI; | ||
| 295 | map_irq.entry_nr = nvec; | ||
| 296 | } else if (type == PCI_CAP_ID_MSIX) { | ||
| 295 | int pos; | 297 | int pos; |
| 296 | u32 table_offset, bir; | 298 | u32 table_offset, bir; |
| 297 | 299 | ||
| @@ -308,6 +310,16 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
| 308 | if (pci_seg_supported) | 310 | if (pci_seg_supported) |
| 309 | ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, | 311 | ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, |
| 310 | &map_irq); | 312 | &map_irq); |
| 313 | if (type == PCI_CAP_ID_MSI && nvec > 1 && ret) { | ||
| 314 | /* | ||
| 315 | * If MAP_PIRQ_TYPE_MULTI_MSI is not available | ||
| 316 | * there's nothing else we can do in this case. | ||
| 317 | * Just set ret > 0 so driver can retry with | ||
| 318 | * single MSI. | ||
| 319 | */ | ||
| 320 | ret = 1; | ||
| 321 | goto out; | ||
| 322 | } | ||
| 311 | if (ret == -EINVAL && !pci_domain_nr(dev->bus)) { | 323 | if (ret == -EINVAL && !pci_domain_nr(dev->bus)) { |
| 312 | map_irq.type = MAP_PIRQ_TYPE_MSI; | 324 | map_irq.type = MAP_PIRQ_TYPE_MSI; |
| 313 | map_irq.index = -1; | 325 | map_irq.index = -1; |
| @@ -324,11 +336,10 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
| 324 | goto out; | 336 | goto out; |
| 325 | } | 337 | } |
| 326 | 338 | ||
| 327 | ret = xen_bind_pirq_msi_to_irq(dev, msidesc, | 339 | ret = xen_bind_pirq_msi_to_irq(dev, msidesc, map_irq.pirq, |
| 328 | map_irq.pirq, | 340 | (type == PCI_CAP_ID_MSI) ? nvec : 1, |
| 329 | (type == PCI_CAP_ID_MSIX) ? | 341 | (type == PCI_CAP_ID_MSIX) ? "msi-x" : "msi", |
| 330 | "msi-x" : "msi", | 342 | domid); |
| 331 | domid); | ||
| 332 | if (ret < 0) | 343 | if (ret < 0) |
| 333 | goto out; | 344 | goto out; |
| 334 | } | 345 | } |
diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig index 9c50cc2e403b..e88fda867a33 100644 --- a/arch/x86/xen/Kconfig +++ b/arch/x86/xen/Kconfig | |||
| @@ -19,11 +19,6 @@ config XEN_DOM0 | |||
| 19 | depends on XEN && PCI_XEN && SWIOTLB_XEN | 19 | depends on XEN && PCI_XEN && SWIOTLB_XEN |
| 20 | depends on X86_LOCAL_APIC && X86_IO_APIC && ACPI && PCI | 20 | depends on X86_LOCAL_APIC && X86_IO_APIC && ACPI && PCI |
| 21 | 21 | ||
| 22 | # Dummy symbol since people have come to rely on the PRIVILEGED_GUEST | ||
| 23 | # name in tools. | ||
| 24 | config XEN_PRIVILEGED_GUEST | ||
| 25 | def_bool XEN_DOM0 | ||
| 26 | |||
| 27 | config XEN_PVHVM | 22 | config XEN_PVHVM |
| 28 | def_bool y | 23 | def_bool y |
| 29 | depends on XEN && PCI && X86_LOCAL_APIC | 24 | depends on XEN && PCI && X86_LOCAL_APIC |
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index 696c694986d0..85e5d78c9874 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c | |||
| @@ -881,6 +881,65 @@ static unsigned long mfn_hash(unsigned long mfn) | |||
| 881 | return hash_long(mfn, M2P_OVERRIDE_HASH_SHIFT); | 881 | return hash_long(mfn, M2P_OVERRIDE_HASH_SHIFT); |
| 882 | } | 882 | } |
| 883 | 883 | ||
| 884 | int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops, | ||
| 885 | struct gnttab_map_grant_ref *kmap_ops, | ||
| 886 | struct page **pages, unsigned int count) | ||
| 887 | { | ||
| 888 | int i, ret = 0; | ||
| 889 | bool lazy = false; | ||
| 890 | pte_t *pte; | ||
| 891 | |||
| 892 | if (xen_feature(XENFEAT_auto_translated_physmap)) | ||
| 893 | return 0; | ||
| 894 | |||
| 895 | if (kmap_ops && | ||
| 896 | !in_interrupt() && | ||
| 897 | paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) { | ||
| 898 | arch_enter_lazy_mmu_mode(); | ||
| 899 | lazy = true; | ||
| 900 | } | ||
| 901 | |||
| 902 | for (i = 0; i < count; i++) { | ||
| 903 | unsigned long mfn, pfn; | ||
| 904 | |||
| 905 | /* Do not add to override if the map failed. */ | ||
| 906 | if (map_ops[i].status) | ||
| 907 | continue; | ||
| 908 | |||
| 909 | if (map_ops[i].flags & GNTMAP_contains_pte) { | ||
| 910 | pte = (pte_t *) (mfn_to_virt(PFN_DOWN(map_ops[i].host_addr)) + | ||
| 911 | (map_ops[i].host_addr & ~PAGE_MASK)); | ||
| 912 | mfn = pte_mfn(*pte); | ||
| 913 | } else { | ||
| 914 | mfn = PFN_DOWN(map_ops[i].dev_bus_addr); | ||
| 915 | } | ||
| 916 | pfn = page_to_pfn(pages[i]); | ||
| 917 | |||
| 918 | WARN_ON(PagePrivate(pages[i])); | ||
| 919 | SetPagePrivate(pages[i]); | ||
| 920 | set_page_private(pages[i], mfn); | ||
| 921 | pages[i]->index = pfn_to_mfn(pfn); | ||
| 922 | |||
| 923 | if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn)))) { | ||
| 924 | ret = -ENOMEM; | ||
| 925 | goto out; | ||
| 926 | } | ||
| 927 | |||
| 928 | if (kmap_ops) { | ||
| 929 | ret = m2p_add_override(mfn, pages[i], &kmap_ops[i]); | ||
| 930 | if (ret) | ||
| 931 | goto out; | ||
| 932 | } | ||
| 933 | } | ||
| 934 | |||
| 935 | out: | ||
| 936 | if (lazy) | ||
| 937 | arch_leave_lazy_mmu_mode(); | ||
| 938 | |||
| 939 | return ret; | ||
| 940 | } | ||
| 941 | EXPORT_SYMBOL_GPL(set_foreign_p2m_mapping); | ||
| 942 | |||
| 884 | /* Add an MFN override for a particular page */ | 943 | /* Add an MFN override for a particular page */ |
| 885 | int m2p_add_override(unsigned long mfn, struct page *page, | 944 | int m2p_add_override(unsigned long mfn, struct page *page, |
| 886 | struct gnttab_map_grant_ref *kmap_op) | 945 | struct gnttab_map_grant_ref *kmap_op) |
| @@ -899,13 +958,6 @@ int m2p_add_override(unsigned long mfn, struct page *page, | |||
| 899 | "m2p_add_override: pfn %lx not mapped", pfn)) | 958 | "m2p_add_override: pfn %lx not mapped", pfn)) |
| 900 | return -EINVAL; | 959 | return -EINVAL; |
| 901 | } | 960 | } |
| 902 | WARN_ON(PagePrivate(page)); | ||
| 903 | SetPagePrivate(page); | ||
| 904 | set_page_private(page, mfn); | ||
| 905 | page->index = pfn_to_mfn(pfn); | ||
| 906 | |||
| 907 | if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn)))) | ||
| 908 | return -ENOMEM; | ||
| 909 | 961 | ||
| 910 | if (kmap_op != NULL) { | 962 | if (kmap_op != NULL) { |
| 911 | if (!PageHighMem(page)) { | 963 | if (!PageHighMem(page)) { |
| @@ -943,20 +995,62 @@ int m2p_add_override(unsigned long mfn, struct page *page, | |||
| 943 | return 0; | 995 | return 0; |
| 944 | } | 996 | } |
| 945 | EXPORT_SYMBOL_GPL(m2p_add_override); | 997 | EXPORT_SYMBOL_GPL(m2p_add_override); |
| 998 | |||
| 999 | int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops, | ||
| 1000 | struct gnttab_map_grant_ref *kmap_ops, | ||
| 1001 | struct page **pages, unsigned int count) | ||
| 1002 | { | ||
| 1003 | int i, ret = 0; | ||
| 1004 | bool lazy = false; | ||
| 1005 | |||
| 1006 | if (xen_feature(XENFEAT_auto_translated_physmap)) | ||
| 1007 | return 0; | ||
| 1008 | |||
| 1009 | if (kmap_ops && | ||
| 1010 | !in_interrupt() && | ||
| 1011 | paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) { | ||
| 1012 | arch_enter_lazy_mmu_mode(); | ||
| 1013 | lazy = true; | ||
| 1014 | } | ||
| 1015 | |||
| 1016 | for (i = 0; i < count; i++) { | ||
| 1017 | unsigned long mfn = get_phys_to_machine(page_to_pfn(pages[i])); | ||
| 1018 | unsigned long pfn = page_to_pfn(pages[i]); | ||
| 1019 | |||
| 1020 | if (mfn == INVALID_P2M_ENTRY || !(mfn & FOREIGN_FRAME_BIT)) { | ||
| 1021 | ret = -EINVAL; | ||
| 1022 | goto out; | ||
| 1023 | } | ||
| 1024 | |||
| 1025 | set_page_private(pages[i], INVALID_P2M_ENTRY); | ||
| 1026 | WARN_ON(!PagePrivate(pages[i])); | ||
| 1027 | ClearPagePrivate(pages[i]); | ||
| 1028 | set_phys_to_machine(pfn, pages[i]->index); | ||
| 1029 | |||
| 1030 | if (kmap_ops) | ||
| 1031 | ret = m2p_remove_override(pages[i], &kmap_ops[i], mfn); | ||
| 1032 | if (ret) | ||
| 1033 | goto out; | ||
| 1034 | } | ||
| 1035 | |||
| 1036 | out: | ||
| 1037 | if (lazy) | ||
| 1038 | arch_leave_lazy_mmu_mode(); | ||
| 1039 | return ret; | ||
| 1040 | } | ||
| 1041 | EXPORT_SYMBOL_GPL(clear_foreign_p2m_mapping); | ||
| 1042 | |||
| 946 | int m2p_remove_override(struct page *page, | 1043 | int m2p_remove_override(struct page *page, |
| 947 | struct gnttab_map_grant_ref *kmap_op) | 1044 | struct gnttab_map_grant_ref *kmap_op, |
| 1045 | unsigned long mfn) | ||
| 948 | { | 1046 | { |
| 949 | unsigned long flags; | 1047 | unsigned long flags; |
| 950 | unsigned long mfn; | ||
| 951 | unsigned long pfn; | 1048 | unsigned long pfn; |
| 952 | unsigned long uninitialized_var(address); | 1049 | unsigned long uninitialized_var(address); |
| 953 | unsigned level; | 1050 | unsigned level; |
| 954 | pte_t *ptep = NULL; | 1051 | pte_t *ptep = NULL; |
| 955 | 1052 | ||
| 956 | pfn = page_to_pfn(page); | 1053 | pfn = page_to_pfn(page); |
| 957 | mfn = get_phys_to_machine(pfn); | ||
| 958 | if (mfn == INVALID_P2M_ENTRY || !(mfn & FOREIGN_FRAME_BIT)) | ||
| 959 | return -EINVAL; | ||
| 960 | 1054 | ||
| 961 | if (!PageHighMem(page)) { | 1055 | if (!PageHighMem(page)) { |
| 962 | address = (unsigned long)__va(pfn << PAGE_SHIFT); | 1056 | address = (unsigned long)__va(pfn << PAGE_SHIFT); |
| @@ -970,10 +1064,7 @@ int m2p_remove_override(struct page *page, | |||
| 970 | spin_lock_irqsave(&m2p_override_lock, flags); | 1064 | spin_lock_irqsave(&m2p_override_lock, flags); |
| 971 | list_del(&page->lru); | 1065 | list_del(&page->lru); |
| 972 | spin_unlock_irqrestore(&m2p_override_lock, flags); | 1066 | spin_unlock_irqrestore(&m2p_override_lock, flags); |
| 973 | WARN_ON(!PagePrivate(page)); | ||
| 974 | ClearPagePrivate(page); | ||
| 975 | 1067 | ||
| 976 | set_phys_to_machine(pfn, page->index); | ||
| 977 | if (kmap_op != NULL) { | 1068 | if (kmap_op != NULL) { |
| 978 | if (!PageHighMem(page)) { | 1069 | if (!PageHighMem(page)) { |
| 979 | struct multicall_space mcs; | 1070 | struct multicall_space mcs; |
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c index c3458f58de90..d5a3de88ac59 100644 --- a/drivers/xen/events/events_base.c +++ b/drivers/xen/events/events_base.c | |||
| @@ -388,10 +388,10 @@ static void xen_irq_init(unsigned irq) | |||
| 388 | list_add_tail(&info->list, &xen_irq_list_head); | 388 | list_add_tail(&info->list, &xen_irq_list_head); |
| 389 | } | 389 | } |
| 390 | 390 | ||
| 391 | static int __must_check xen_allocate_irq_dynamic(void) | 391 | static int __must_check xen_allocate_irqs_dynamic(int nvec) |
| 392 | { | 392 | { |
| 393 | int first = 0; | 393 | int first = 0; |
| 394 | int irq; | 394 | int i, irq; |
| 395 | 395 | ||
| 396 | #ifdef CONFIG_X86_IO_APIC | 396 | #ifdef CONFIG_X86_IO_APIC |
| 397 | /* | 397 | /* |
| @@ -405,14 +405,22 @@ static int __must_check xen_allocate_irq_dynamic(void) | |||
| 405 | first = get_nr_irqs_gsi(); | 405 | first = get_nr_irqs_gsi(); |
| 406 | #endif | 406 | #endif |
| 407 | 407 | ||
| 408 | irq = irq_alloc_desc_from(first, -1); | 408 | irq = irq_alloc_descs_from(first, nvec, -1); |
| 409 | 409 | ||
| 410 | if (irq >= 0) | 410 | if (irq >= 0) { |
| 411 | xen_irq_init(irq); | 411 | for (i = 0; i < nvec; i++) |
| 412 | xen_irq_init(irq + i); | ||
| 413 | } | ||
| 412 | 414 | ||
| 413 | return irq; | 415 | return irq; |
| 414 | } | 416 | } |
| 415 | 417 | ||
| 418 | static inline int __must_check xen_allocate_irq_dynamic(void) | ||
| 419 | { | ||
| 420 | |||
| 421 | return xen_allocate_irqs_dynamic(1); | ||
| 422 | } | ||
| 423 | |||
| 416 | static int __must_check xen_allocate_irq_gsi(unsigned gsi) | 424 | static int __must_check xen_allocate_irq_gsi(unsigned gsi) |
| 417 | { | 425 | { |
| 418 | int irq; | 426 | int irq; |
| @@ -466,9 +474,6 @@ static void xen_evtchn_close(unsigned int port) | |||
| 466 | close.port = port; | 474 | close.port = port; |
| 467 | if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0) | 475 | if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0) |
| 468 | BUG(); | 476 | BUG(); |
| 469 | |||
| 470 | /* Closed ports are implicitly re-bound to VCPU0. */ | ||
| 471 | bind_evtchn_to_cpu(port, 0); | ||
| 472 | } | 477 | } |
| 473 | 478 | ||
| 474 | static void pirq_query_unmask(int irq) | 479 | static void pirq_query_unmask(int irq) |
| @@ -730,22 +735,25 @@ int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc) | |||
| 730 | } | 735 | } |
| 731 | 736 | ||
| 732 | int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, | 737 | int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, |
| 733 | int pirq, const char *name, domid_t domid) | 738 | int pirq, int nvec, const char *name, domid_t domid) |
| 734 | { | 739 | { |
| 735 | int irq, ret; | 740 | int i, irq, ret; |
| 736 | 741 | ||
| 737 | mutex_lock(&irq_mapping_update_lock); | 742 | mutex_lock(&irq_mapping_update_lock); |
| 738 | 743 | ||
| 739 | irq = xen_allocate_irq_dynamic(); | 744 | irq = xen_allocate_irqs_dynamic(nvec); |
| 740 | if (irq < 0) | 745 | if (irq < 0) |
| 741 | goto out; | 746 | goto out; |
| 742 | 747 | ||
| 743 | irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_edge_irq, | 748 | for (i = 0; i < nvec; i++) { |
| 744 | name); | 749 | irq_set_chip_and_handler_name(irq + i, &xen_pirq_chip, handle_edge_irq, name); |
| 750 | |||
| 751 | ret = xen_irq_info_pirq_setup(irq + i, 0, pirq + i, 0, domid, | ||
| 752 | i == 0 ? 0 : PIRQ_MSI_GROUP); | ||
| 753 | if (ret < 0) | ||
| 754 | goto error_irq; | ||
| 755 | } | ||
| 745 | 756 | ||
| 746 | ret = xen_irq_info_pirq_setup(irq, 0, pirq, 0, domid, 0); | ||
| 747 | if (ret < 0) | ||
| 748 | goto error_irq; | ||
| 749 | ret = irq_set_msi_desc(irq, msidesc); | 757 | ret = irq_set_msi_desc(irq, msidesc); |
| 750 | if (ret < 0) | 758 | if (ret < 0) |
| 751 | goto error_irq; | 759 | goto error_irq; |
| @@ -753,7 +761,8 @@ out: | |||
| 753 | mutex_unlock(&irq_mapping_update_lock); | 761 | mutex_unlock(&irq_mapping_update_lock); |
| 754 | return irq; | 762 | return irq; |
| 755 | error_irq: | 763 | error_irq: |
| 756 | __unbind_from_irq(irq); | 764 | for (; i >= 0; i--) |
| 765 | __unbind_from_irq(irq + i); | ||
| 757 | mutex_unlock(&irq_mapping_update_lock); | 766 | mutex_unlock(&irq_mapping_update_lock); |
| 758 | return ret; | 767 | return ret; |
| 759 | } | 768 | } |
| @@ -767,7 +776,12 @@ int xen_destroy_irq(int irq) | |||
| 767 | 776 | ||
| 768 | mutex_lock(&irq_mapping_update_lock); | 777 | mutex_lock(&irq_mapping_update_lock); |
| 769 | 778 | ||
| 770 | if (xen_initial_domain()) { | 779 | /* |
| 780 | * If trying to remove a vector in a MSI group different | ||
| 781 | * than the first one skip the PIRQ unmap unless this vector | ||
| 782 | * is the first one in the group. | ||
| 783 | */ | ||
| 784 | if (xen_initial_domain() && !(info->u.pirq.flags & PIRQ_MSI_GROUP)) { | ||
| 771 | unmap_irq.pirq = info->u.pirq.pirq; | 785 | unmap_irq.pirq = info->u.pirq.pirq; |
| 772 | unmap_irq.domid = info->u.pirq.domid; | 786 | unmap_irq.domid = info->u.pirq.domid; |
| 773 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap_irq); | 787 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap_irq); |
| @@ -1329,26 +1343,6 @@ static int set_affinity_irq(struct irq_data *data, const struct cpumask *dest, | |||
| 1329 | return rebind_irq_to_cpu(data->irq, tcpu); | 1343 | return rebind_irq_to_cpu(data->irq, tcpu); |
| 1330 | } | 1344 | } |
| 1331 | 1345 | ||
| 1332 | static int retrigger_evtchn(int evtchn) | ||
| 1333 | { | ||
| 1334 | int masked; | ||
| 1335 | |||
| 1336 | if (!VALID_EVTCHN(evtchn)) | ||
| 1337 | return 0; | ||
| 1338 | |||
| 1339 | masked = test_and_set_mask(evtchn); | ||
| 1340 | set_evtchn(evtchn); | ||
| 1341 | if (!masked) | ||
| 1342 | unmask_evtchn(evtchn); | ||
| 1343 | |||
| 1344 | return 1; | ||
| 1345 | } | ||
| 1346 | |||
| 1347 | int resend_irq_on_evtchn(unsigned int irq) | ||
| 1348 | { | ||
| 1349 | return retrigger_evtchn(evtchn_from_irq(irq)); | ||
| 1350 | } | ||
| 1351 | |||
| 1352 | static void enable_dynirq(struct irq_data *data) | 1346 | static void enable_dynirq(struct irq_data *data) |
| 1353 | { | 1347 | { |
| 1354 | int evtchn = evtchn_from_irq(data->irq); | 1348 | int evtchn = evtchn_from_irq(data->irq); |
| @@ -1383,7 +1377,18 @@ static void mask_ack_dynirq(struct irq_data *data) | |||
| 1383 | 1377 | ||
| 1384 | static int retrigger_dynirq(struct irq_data *data) | 1378 | static int retrigger_dynirq(struct irq_data *data) |
| 1385 | { | 1379 | { |
| 1386 | return retrigger_evtchn(evtchn_from_irq(data->irq)); | 1380 | unsigned int evtchn = evtchn_from_irq(data->irq); |
| 1381 | int masked; | ||
| 1382 | |||
| 1383 | if (!VALID_EVTCHN(evtchn)) | ||
| 1384 | return 0; | ||
| 1385 | |||
| 1386 | masked = test_and_set_mask(evtchn); | ||
| 1387 | set_evtchn(evtchn); | ||
| 1388 | if (!masked) | ||
| 1389 | unmask_evtchn(evtchn); | ||
| 1390 | |||
| 1391 | return 1; | ||
| 1387 | } | 1392 | } |
| 1388 | 1393 | ||
| 1389 | static void restore_pirqs(void) | 1394 | static void restore_pirqs(void) |
diff --git a/drivers/xen/events/events_internal.h b/drivers/xen/events/events_internal.h index 677f41a0fff9..50c2050a1e32 100644 --- a/drivers/xen/events/events_internal.h +++ b/drivers/xen/events/events_internal.h | |||
| @@ -53,6 +53,7 @@ struct irq_info { | |||
| 53 | 53 | ||
| 54 | #define PIRQ_NEEDS_EOI (1 << 0) | 54 | #define PIRQ_NEEDS_EOI (1 << 0) |
| 55 | #define PIRQ_SHAREABLE (1 << 1) | 55 | #define PIRQ_SHAREABLE (1 << 1) |
| 56 | #define PIRQ_MSI_GROUP (1 << 2) | ||
| 56 | 57 | ||
| 57 | struct evtchn_ops { | 58 | struct evtchn_ops { |
| 58 | unsigned (*max_channels)(void); | 59 | unsigned (*max_channels)(void); |
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index b84e3ab839aa..6d325bda76da 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c | |||
| @@ -933,9 +933,6 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, | |||
| 933 | struct page **pages, unsigned int count) | 933 | struct page **pages, unsigned int count) |
| 934 | { | 934 | { |
| 935 | int i, ret; | 935 | int i, ret; |
| 936 | bool lazy = false; | ||
| 937 | pte_t *pte; | ||
| 938 | unsigned long mfn; | ||
| 939 | 936 | ||
| 940 | ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map_ops, count); | 937 | ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map_ops, count); |
| 941 | if (ret) | 938 | if (ret) |
| @@ -947,45 +944,7 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, | |||
| 947 | gnttab_retry_eagain_gop(GNTTABOP_map_grant_ref, map_ops + i, | 944 | gnttab_retry_eagain_gop(GNTTABOP_map_grant_ref, map_ops + i, |
| 948 | &map_ops[i].status, __func__); | 945 | &map_ops[i].status, __func__); |
| 949 | 946 | ||
| 950 | /* this is basically a nop on x86 */ | 947 | return set_foreign_p2m_mapping(map_ops, kmap_ops, pages, count); |
| 951 | if (xen_feature(XENFEAT_auto_translated_physmap)) { | ||
| 952 | for (i = 0; i < count; i++) { | ||
| 953 | if (map_ops[i].status) | ||
| 954 | continue; | ||
| 955 | set_phys_to_machine(map_ops[i].host_addr >> PAGE_SHIFT, | ||
| 956 | map_ops[i].dev_bus_addr >> PAGE_SHIFT); | ||
| 957 | } | ||
| 958 | return ret; | ||
| 959 | } | ||
| 960 | |||
| 961 | if (!in_interrupt() && paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) { | ||
| 962 | arch_enter_lazy_mmu_mode(); | ||
| 963 | lazy = true; | ||
| 964 | } | ||
| 965 | |||
| 966 | for (i = 0; i < count; i++) { | ||
| 967 | /* Do not add to override if the map failed. */ | ||
| 968 | if (map_ops[i].status) | ||
| 969 | continue; | ||
| 970 | |||
| 971 | if (map_ops[i].flags & GNTMAP_contains_pte) { | ||
| 972 | pte = (pte_t *) (mfn_to_virt(PFN_DOWN(map_ops[i].host_addr)) + | ||
| 973 | (map_ops[i].host_addr & ~PAGE_MASK)); | ||
| 974 | mfn = pte_mfn(*pte); | ||
| 975 | } else { | ||
| 976 | mfn = PFN_DOWN(map_ops[i].dev_bus_addr); | ||
| 977 | } | ||
| 978 | ret = m2p_add_override(mfn, pages[i], kmap_ops ? | ||
| 979 | &kmap_ops[i] : NULL); | ||
| 980 | if (ret) | ||
| 981 | goto out; | ||
| 982 | } | ||
| 983 | |||
| 984 | out: | ||
| 985 | if (lazy) | ||
| 986 | arch_leave_lazy_mmu_mode(); | ||
| 987 | |||
| 988 | return ret; | ||
| 989 | } | 948 | } |
| 990 | EXPORT_SYMBOL_GPL(gnttab_map_refs); | 949 | EXPORT_SYMBOL_GPL(gnttab_map_refs); |
| 991 | 950 | ||
| @@ -993,39 +952,13 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, | |||
| 993 | struct gnttab_map_grant_ref *kmap_ops, | 952 | struct gnttab_map_grant_ref *kmap_ops, |
| 994 | struct page **pages, unsigned int count) | 953 | struct page **pages, unsigned int count) |
| 995 | { | 954 | { |
| 996 | int i, ret; | 955 | int ret; |
| 997 | bool lazy = false; | ||
| 998 | 956 | ||
| 999 | ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap_ops, count); | 957 | ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap_ops, count); |
| 1000 | if (ret) | 958 | if (ret) |
| 1001 | return ret; | 959 | return ret; |
| 1002 | 960 | ||
| 1003 | /* this is basically a nop on x86 */ | 961 | return clear_foreign_p2m_mapping(unmap_ops, kmap_ops, pages, count); |
| 1004 | if (xen_feature(XENFEAT_auto_translated_physmap)) { | ||
| 1005 | for (i = 0; i < count; i++) { | ||
| 1006 | set_phys_to_machine(unmap_ops[i].host_addr >> PAGE_SHIFT, | ||
| 1007 | INVALID_P2M_ENTRY); | ||
| 1008 | } | ||
| 1009 | return ret; | ||
| 1010 | } | ||
| 1011 | |||
| 1012 | if (!in_interrupt() && paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) { | ||
| 1013 | arch_enter_lazy_mmu_mode(); | ||
| 1014 | lazy = true; | ||
| 1015 | } | ||
| 1016 | |||
| 1017 | for (i = 0; i < count; i++) { | ||
| 1018 | ret = m2p_remove_override(pages[i], kmap_ops ? | ||
| 1019 | &kmap_ops[i] : NULL); | ||
| 1020 | if (ret) | ||
| 1021 | goto out; | ||
| 1022 | } | ||
| 1023 | |||
| 1024 | out: | ||
| 1025 | if (lazy) | ||
| 1026 | arch_leave_lazy_mmu_mode(); | ||
| 1027 | |||
| 1028 | return ret; | ||
| 1029 | } | 962 | } |
| 1030 | EXPORT_SYMBOL_GPL(gnttab_unmap_refs); | 963 | EXPORT_SYMBOL_GPL(gnttab_unmap_refs); |
| 1031 | 964 | ||
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 624e8dc24532..fc6c94c0b436 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c | |||
| @@ -46,6 +46,20 @@ struct suspend_info { | |||
| 46 | void (*post)(int cancelled); | 46 | void (*post)(int cancelled); |
| 47 | }; | 47 | }; |
| 48 | 48 | ||
| 49 | static RAW_NOTIFIER_HEAD(xen_resume_notifier); | ||
| 50 | |||
| 51 | void xen_resume_notifier_register(struct notifier_block *nb) | ||
| 52 | { | ||
| 53 | raw_notifier_chain_register(&xen_resume_notifier, nb); | ||
| 54 | } | ||
| 55 | EXPORT_SYMBOL_GPL(xen_resume_notifier_register); | ||
| 56 | |||
| 57 | void xen_resume_notifier_unregister(struct notifier_block *nb) | ||
| 58 | { | ||
| 59 | raw_notifier_chain_unregister(&xen_resume_notifier, nb); | ||
| 60 | } | ||
| 61 | EXPORT_SYMBOL_GPL(xen_resume_notifier_unregister); | ||
| 62 | |||
| 49 | #ifdef CONFIG_HIBERNATE_CALLBACKS | 63 | #ifdef CONFIG_HIBERNATE_CALLBACKS |
| 50 | static void xen_hvm_post_suspend(int cancelled) | 64 | static void xen_hvm_post_suspend(int cancelled) |
| 51 | { | 65 | { |
| @@ -152,6 +166,8 @@ static void do_suspend(void) | |||
| 152 | 166 | ||
| 153 | err = stop_machine(xen_suspend, &si, cpumask_of(0)); | 167 | err = stop_machine(xen_suspend, &si, cpumask_of(0)); |
| 154 | 168 | ||
| 169 | raw_notifier_call_chain(&xen_resume_notifier, 0, NULL); | ||
| 170 | |||
| 155 | dpm_resume_start(si.cancelled ? PMSG_THAW : PMSG_RESTORE); | 171 | dpm_resume_start(si.cancelled ? PMSG_THAW : PMSG_RESTORE); |
| 156 | 172 | ||
| 157 | if (err) { | 173 | if (err) { |
diff --git a/drivers/xen/pcpu.c b/drivers/xen/pcpu.c index 79e1dff7ed4f..0aac403d53fd 100644 --- a/drivers/xen/pcpu.c +++ b/drivers/xen/pcpu.c | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | #include <linux/capability.h> | 40 | #include <linux/capability.h> |
| 41 | 41 | ||
| 42 | #include <xen/xen.h> | 42 | #include <xen/xen.h> |
| 43 | #include <xen/acpi.h> | ||
| 43 | #include <xen/xenbus.h> | 44 | #include <xen/xenbus.h> |
| 44 | #include <xen/events.h> | 45 | #include <xen/events.h> |
| 45 | #include <xen/interface/platform.h> | 46 | #include <xen/interface/platform.h> |
diff --git a/drivers/xen/platform-pci.c b/drivers/xen/platform-pci.c index a1361c312c06..3454973dc3bb 100644 --- a/drivers/xen/platform-pci.c +++ b/drivers/xen/platform-pci.c | |||
| @@ -45,7 +45,7 @@ static unsigned long platform_mmio_alloc; | |||
| 45 | static unsigned long platform_mmiolen; | 45 | static unsigned long platform_mmiolen; |
| 46 | static uint64_t callback_via; | 46 | static uint64_t callback_via; |
| 47 | 47 | ||
| 48 | unsigned long alloc_xen_mmio(unsigned long len) | 48 | static unsigned long alloc_xen_mmio(unsigned long len) |
| 49 | { | 49 | { |
| 50 | unsigned long addr; | 50 | unsigned long addr; |
| 51 | 51 | ||
diff --git a/drivers/xen/xen-acpi-processor.c b/drivers/xen/xen-acpi-processor.c index 7231859119f1..82358d14ecf1 100644 --- a/drivers/xen/xen-acpi-processor.c +++ b/drivers/xen/xen-acpi-processor.c | |||
| @@ -27,10 +27,10 @@ | |||
| 27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
| 28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
| 29 | #include <linux/types.h> | 29 | #include <linux/types.h> |
| 30 | #include <linux/syscore_ops.h> | ||
| 31 | #include <linux/acpi.h> | 30 | #include <linux/acpi.h> |
| 32 | #include <acpi/processor.h> | 31 | #include <acpi/processor.h> |
| 33 | #include <xen/xen.h> | 32 | #include <xen/xen.h> |
| 33 | #include <xen/xen-ops.h> | ||
| 34 | #include <xen/interface/platform.h> | 34 | #include <xen/interface/platform.h> |
| 35 | #include <asm/xen/hypercall.h> | 35 | #include <asm/xen/hypercall.h> |
| 36 | 36 | ||
| @@ -495,14 +495,15 @@ static int xen_upload_processor_pm_data(void) | |||
| 495 | return rc; | 495 | return rc; |
| 496 | } | 496 | } |
| 497 | 497 | ||
| 498 | static void xen_acpi_processor_resume(void) | 498 | static int xen_acpi_processor_resume(struct notifier_block *nb, |
| 499 | unsigned long action, void *data) | ||
| 499 | { | 500 | { |
| 500 | bitmap_zero(acpi_ids_done, nr_acpi_bits); | 501 | bitmap_zero(acpi_ids_done, nr_acpi_bits); |
| 501 | xen_upload_processor_pm_data(); | 502 | return xen_upload_processor_pm_data(); |
| 502 | } | 503 | } |
| 503 | 504 | ||
| 504 | static struct syscore_ops xap_syscore_ops = { | 505 | struct notifier_block xen_acpi_processor_resume_nb = { |
| 505 | .resume = xen_acpi_processor_resume, | 506 | .notifier_call = xen_acpi_processor_resume, |
| 506 | }; | 507 | }; |
| 507 | 508 | ||
| 508 | static int __init xen_acpi_processor_init(void) | 509 | static int __init xen_acpi_processor_init(void) |
| @@ -555,7 +556,7 @@ static int __init xen_acpi_processor_init(void) | |||
| 555 | if (rc) | 556 | if (rc) |
| 556 | goto err_unregister; | 557 | goto err_unregister; |
| 557 | 558 | ||
| 558 | register_syscore_ops(&xap_syscore_ops); | 559 | xen_resume_notifier_register(&xen_acpi_processor_resume_nb); |
| 559 | 560 | ||
| 560 | return 0; | 561 | return 0; |
| 561 | err_unregister: | 562 | err_unregister: |
| @@ -574,7 +575,7 @@ static void __exit xen_acpi_processor_exit(void) | |||
| 574 | { | 575 | { |
| 575 | int i; | 576 | int i; |
| 576 | 577 | ||
| 577 | unregister_syscore_ops(&xap_syscore_ops); | 578 | xen_resume_notifier_unregister(&xen_acpi_processor_resume_nb); |
| 578 | kfree(acpi_ids_done); | 579 | kfree(acpi_ids_done); |
| 579 | kfree(acpi_id_present); | 580 | kfree(acpi_id_present); |
| 580 | kfree(acpi_id_cst_present); | 581 | kfree(acpi_id_cst_present); |
diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c index 64eb0cd8b8af..929dd46bb40c 100644 --- a/drivers/xen/xen-pciback/pciback_ops.c +++ b/drivers/xen/xen-pciback/pciback_ops.c | |||
| @@ -213,8 +213,7 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev, | |||
| 213 | entries[i].vector = op->msix_entries[i].vector; | 213 | entries[i].vector = op->msix_entries[i].vector; |
| 214 | } | 214 | } |
| 215 | 215 | ||
| 216 | result = pci_enable_msix(dev, entries, op->value); | 216 | result = pci_enable_msix_exact(dev, entries, op->value); |
| 217 | |||
| 218 | if (result == 0) { | 217 | if (result == 0) { |
| 219 | for (i = 0; i < op->value; i++) { | 218 | for (i = 0; i < op->value; i++) { |
| 220 | op->msix_entries[i].entry = entries[i].entry; | 219 | op->msix_entries[i].entry = entries[i].entry; |
diff --git a/drivers/xen/xen-selfballoon.c b/drivers/xen/xen-selfballoon.c index 745ad79c1d8e..3b2bffde534f 100644 --- a/drivers/xen/xen-selfballoon.c +++ b/drivers/xen/xen-selfballoon.c | |||
| @@ -170,6 +170,7 @@ static void frontswap_selfshrink(void) | |||
| 170 | tgt_frontswap_pages = cur_frontswap_pages - | 170 | tgt_frontswap_pages = cur_frontswap_pages - |
| 171 | (cur_frontswap_pages / frontswap_hysteresis); | 171 | (cur_frontswap_pages / frontswap_hysteresis); |
| 172 | frontswap_shrink(tgt_frontswap_pages); | 172 | frontswap_shrink(tgt_frontswap_pages); |
| 173 | frontswap_inertia_counter = frontswap_inertia; | ||
| 173 | } | 174 | } |
| 174 | 175 | ||
| 175 | #endif /* CONFIG_FRONTSWAP */ | 176 | #endif /* CONFIG_FRONTSWAP */ |
diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c index 01d59e66565d..439c9dca9eee 100644 --- a/drivers/xen/xenbus/xenbus_client.c +++ b/drivers/xen/xenbus/xenbus_client.c | |||
| @@ -401,33 +401,6 @@ EXPORT_SYMBOL_GPL(xenbus_alloc_evtchn); | |||
| 401 | 401 | ||
| 402 | 402 | ||
| 403 | /** | 403 | /** |
| 404 | * Bind to an existing interdomain event channel in another domain. Returns 0 | ||
| 405 | * on success and stores the local port in *port. On error, returns -errno, | ||
| 406 | * switches the device to XenbusStateClosing, and saves the error in XenStore. | ||
| 407 | */ | ||
| 408 | int xenbus_bind_evtchn(struct xenbus_device *dev, int remote_port, int *port) | ||
| 409 | { | ||
| 410 | struct evtchn_bind_interdomain bind_interdomain; | ||
| 411 | int err; | ||
| 412 | |||
| 413 | bind_interdomain.remote_dom = dev->otherend_id; | ||
| 414 | bind_interdomain.remote_port = remote_port; | ||
| 415 | |||
| 416 | err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain, | ||
| 417 | &bind_interdomain); | ||
| 418 | if (err) | ||
| 419 | xenbus_dev_fatal(dev, err, | ||
| 420 | "binding to event channel %d from domain %d", | ||
| 421 | remote_port, dev->otherend_id); | ||
| 422 | else | ||
| 423 | *port = bind_interdomain.local_port; | ||
| 424 | |||
| 425 | return err; | ||
| 426 | } | ||
| 427 | EXPORT_SYMBOL_GPL(xenbus_bind_evtchn); | ||
| 428 | |||
| 429 | |||
| 430 | /** | ||
| 431 | * Free an existing event channel. Returns 0 on success or -errno on error. | 404 | * Free an existing event channel. Returns 0 on success or -errno on error. |
| 432 | */ | 405 | */ |
| 433 | int xenbus_free_evtchn(struct xenbus_device *dev, int port) | 406 | int xenbus_free_evtchn(struct xenbus_device *dev, int port) |
diff --git a/include/xen/events.h b/include/xen/events.h index c9c85cf84895..8bee7a75e850 100644 --- a/include/xen/events.h +++ b/include/xen/events.h | |||
| @@ -2,6 +2,9 @@ | |||
| 2 | #define _XEN_EVENTS_H | 2 | #define _XEN_EVENTS_H |
| 3 | 3 | ||
| 4 | #include <linux/interrupt.h> | 4 | #include <linux/interrupt.h> |
| 5 | #ifdef CONFIG_PCI_MSI | ||
| 6 | #include <linux/msi.h> | ||
| 7 | #endif | ||
| 5 | 8 | ||
| 6 | #include <xen/interface/event_channel.h> | 9 | #include <xen/interface/event_channel.h> |
| 7 | #include <asm/xen/hypercall.h> | 10 | #include <asm/xen/hypercall.h> |
| @@ -52,7 +55,6 @@ int evtchn_get(unsigned int evtchn); | |||
| 52 | void evtchn_put(unsigned int evtchn); | 55 | void evtchn_put(unsigned int evtchn); |
| 53 | 56 | ||
| 54 | void xen_send_IPI_one(unsigned int cpu, enum ipi_vector vector); | 57 | void xen_send_IPI_one(unsigned int cpu, enum ipi_vector vector); |
| 55 | int resend_irq_on_evtchn(unsigned int irq); | ||
| 56 | void rebind_evtchn_irq(int evtchn, int irq); | 58 | void rebind_evtchn_irq(int evtchn, int irq); |
| 57 | 59 | ||
| 58 | static inline void notify_remote_via_evtchn(int port) | 60 | static inline void notify_remote_via_evtchn(int port) |
| @@ -102,7 +104,7 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi, | |||
| 102 | int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc); | 104 | int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc); |
| 103 | /* Bind an PSI pirq to an irq. */ | 105 | /* Bind an PSI pirq to an irq. */ |
| 104 | int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, | 106 | int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, |
| 105 | int pirq, const char *name, domid_t domid); | 107 | int pirq, int nvec, const char *name, domid_t domid); |
| 106 | #endif | 108 | #endif |
| 107 | 109 | ||
| 108 | /* De-allocates the above mentioned physical interrupt. */ | 110 | /* De-allocates the above mentioned physical interrupt. */ |
diff --git a/include/xen/interface/physdev.h b/include/xen/interface/physdev.h index 42721d13a106..610dba9b620a 100644 --- a/include/xen/interface/physdev.h +++ b/include/xen/interface/physdev.h | |||
| @@ -131,6 +131,7 @@ struct physdev_irq { | |||
| 131 | #define MAP_PIRQ_TYPE_GSI 0x1 | 131 | #define MAP_PIRQ_TYPE_GSI 0x1 |
| 132 | #define MAP_PIRQ_TYPE_UNKNOWN 0x2 | 132 | #define MAP_PIRQ_TYPE_UNKNOWN 0x2 |
| 133 | #define MAP_PIRQ_TYPE_MSI_SEG 0x3 | 133 | #define MAP_PIRQ_TYPE_MSI_SEG 0x3 |
| 134 | #define MAP_PIRQ_TYPE_MULTI_MSI 0x4 | ||
| 134 | 135 | ||
| 135 | #define PHYSDEVOP_map_pirq 13 | 136 | #define PHYSDEVOP_map_pirq 13 |
| 136 | struct physdev_map_pirq { | 137 | struct physdev_map_pirq { |
| @@ -141,11 +142,16 @@ struct physdev_map_pirq { | |||
| 141 | int index; | 142 | int index; |
| 142 | /* IN or OUT */ | 143 | /* IN or OUT */ |
| 143 | int pirq; | 144 | int pirq; |
| 144 | /* IN - high 16 bits hold segment for MAP_PIRQ_TYPE_MSI_SEG */ | 145 | /* IN - high 16 bits hold segment for ..._MSI_SEG and ..._MULTI_MSI */ |
| 145 | int bus; | 146 | int bus; |
| 146 | /* IN */ | 147 | /* IN */ |
| 147 | int devfn; | 148 | int devfn; |
| 148 | /* IN */ | 149 | /* IN |
| 150 | * - For MSI-X contains entry number. | ||
| 151 | * - For MSI with ..._MULTI_MSI contains number of vectors. | ||
| 152 | * OUT (..._MULTI_MSI only) | ||
| 153 | * - Number of vectors allocated. | ||
| 154 | */ | ||
| 149 | int entry_nr; | 155 | int entry_nr; |
| 150 | /* IN */ | 156 | /* IN */ |
| 151 | uint64_t table_base; | 157 | uint64_t table_base; |
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h index fb2ea8f26552..2cf47175b12b 100644 --- a/include/xen/xen-ops.h +++ b/include/xen/xen-ops.h | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | #define INCLUDE_XEN_OPS_H | 2 | #define INCLUDE_XEN_OPS_H |
| 3 | 3 | ||
| 4 | #include <linux/percpu.h> | 4 | #include <linux/percpu.h> |
| 5 | #include <linux/notifier.h> | ||
| 5 | #include <asm/xen/interface.h> | 6 | #include <asm/xen/interface.h> |
| 6 | 7 | ||
| 7 | DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu); | 8 | DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu); |
| @@ -16,6 +17,9 @@ void xen_mm_unpin_all(void); | |||
| 16 | void xen_timer_resume(void); | 17 | void xen_timer_resume(void); |
| 17 | void xen_arch_resume(void); | 18 | void xen_arch_resume(void); |
| 18 | 19 | ||
| 20 | void xen_resume_notifier_register(struct notifier_block *nb); | ||
| 21 | void xen_resume_notifier_unregister(struct notifier_block *nb); | ||
| 22 | |||
| 19 | int xen_setup_shutdown_event(void); | 23 | int xen_setup_shutdown_event(void); |
| 20 | 24 | ||
| 21 | extern unsigned long *xen_contiguous_bitmap; | 25 | extern unsigned long *xen_contiguous_bitmap; |
diff --git a/include/xen/xenbus.h b/include/xen/xenbus.h index 569c07f2e344..0324c6d340c1 100644 --- a/include/xen/xenbus.h +++ b/include/xen/xenbus.h | |||
| @@ -207,7 +207,6 @@ int xenbus_unmap_ring(struct xenbus_device *dev, | |||
| 207 | grant_handle_t handle, void *vaddr); | 207 | grant_handle_t handle, void *vaddr); |
| 208 | 208 | ||
| 209 | int xenbus_alloc_evtchn(struct xenbus_device *dev, int *port); | 209 | int xenbus_alloc_evtchn(struct xenbus_device *dev, int *port); |
| 210 | int xenbus_bind_evtchn(struct xenbus_device *dev, int remote_port, int *port); | ||
| 211 | int xenbus_free_evtchn(struct xenbus_device *dev, int port); | 210 | int xenbus_free_evtchn(struct xenbus_device *dev, int port); |
| 212 | 211 | ||
| 213 | enum xenbus_state xenbus_read_driver_state(const char *path); | 212 | enum xenbus_state xenbus_read_driver_state(const char *path); |
