diff options
| -rw-r--r-- | arch/x86/xen/enlighten.c | 8 | ||||
| -rw-r--r-- | arch/x86/xen/p2m.c | 36 | ||||
| -rw-r--r-- | arch/x86/xen/setup.c | 3 | ||||
| -rw-r--r-- | drivers/tty/hvc/hvc_xen.c | 31 | ||||
| -rw-r--r-- | drivers/xen/events.c | 9 | ||||
| -rw-r--r-- | drivers/xen/pci.c | 2 |
6 files changed, 73 insertions, 16 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index e74df9548a02..ff962d4b821e 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
| @@ -209,6 +209,9 @@ static void __init xen_banner(void) | |||
| 209 | xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : ""); | 209 | xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : ""); |
| 210 | } | 210 | } |
| 211 | 211 | ||
| 212 | #define CPUID_THERM_POWER_LEAF 6 | ||
| 213 | #define APERFMPERF_PRESENT 0 | ||
| 214 | |||
| 212 | static __read_mostly unsigned int cpuid_leaf1_edx_mask = ~0; | 215 | static __read_mostly unsigned int cpuid_leaf1_edx_mask = ~0; |
| 213 | static __read_mostly unsigned int cpuid_leaf1_ecx_mask = ~0; | 216 | static __read_mostly unsigned int cpuid_leaf1_ecx_mask = ~0; |
| 214 | 217 | ||
| @@ -242,6 +245,11 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx, | |||
| 242 | *dx = cpuid_leaf5_edx_val; | 245 | *dx = cpuid_leaf5_edx_val; |
| 243 | return; | 246 | return; |
| 244 | 247 | ||
| 248 | case CPUID_THERM_POWER_LEAF: | ||
| 249 | /* Disabling APERFMPERF for kernel usage */ | ||
| 250 | maskecx = ~(1 << APERFMPERF_PRESENT); | ||
| 251 | break; | ||
| 252 | |||
| 245 | case 0xb: | 253 | case 0xb: |
| 246 | /* Suppress extended topology stuff */ | 254 | /* Suppress extended topology stuff */ |
| 247 | maskebx = 0; | 255 | maskebx = 0; |
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index ffd08c414e91..64effdc6da94 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c | |||
| @@ -706,6 +706,7 @@ int m2p_add_override(unsigned long mfn, struct page *page, | |||
| 706 | unsigned long uninitialized_var(address); | 706 | unsigned long uninitialized_var(address); |
| 707 | unsigned level; | 707 | unsigned level; |
| 708 | pte_t *ptep = NULL; | 708 | pte_t *ptep = NULL; |
| 709 | int ret = 0; | ||
| 709 | 710 | ||
| 710 | pfn = page_to_pfn(page); | 711 | pfn = page_to_pfn(page); |
| 711 | if (!PageHighMem(page)) { | 712 | if (!PageHighMem(page)) { |
| @@ -741,6 +742,24 @@ int m2p_add_override(unsigned long mfn, struct page *page, | |||
| 741 | list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]); | 742 | list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]); |
| 742 | spin_unlock_irqrestore(&m2p_override_lock, flags); | 743 | spin_unlock_irqrestore(&m2p_override_lock, flags); |
| 743 | 744 | ||
| 745 | /* p2m(m2p(mfn)) == mfn: the mfn is already present somewhere in | ||
| 746 | * this domain. Set the FOREIGN_FRAME_BIT in the p2m for the other | ||
| 747 | * pfn so that the following mfn_to_pfn(mfn) calls will return the | ||
| 748 | * pfn from the m2p_override (the backend pfn) instead. | ||
| 749 | * We need to do this because the pages shared by the frontend | ||
| 750 | * (xen-blkfront) can be already locked (lock_page, called by | ||
| 751 | * do_read_cache_page); when the userspace backend tries to use them | ||
| 752 | * with direct_IO, mfn_to_pfn returns the pfn of the frontend, so | ||
| 753 | * do_blockdev_direct_IO is going to try to lock the same pages | ||
| 754 | * again resulting in a deadlock. | ||
| 755 | * As a side effect get_user_pages_fast might not be safe on the | ||
| 756 | * frontend pages while they are being shared with the backend, | ||
| 757 | * because mfn_to_pfn (that ends up being called by GUPF) will | ||
| 758 | * return the backend pfn rather than the frontend pfn. */ | ||
| 759 | ret = __get_user(pfn, &machine_to_phys_mapping[mfn]); | ||
| 760 | if (ret == 0 && get_phys_to_machine(pfn) == mfn) | ||
| 761 | set_phys_to_machine(pfn, FOREIGN_FRAME(mfn)); | ||
| 762 | |||
| 744 | return 0; | 763 | return 0; |
| 745 | } | 764 | } |
| 746 | EXPORT_SYMBOL_GPL(m2p_add_override); | 765 | EXPORT_SYMBOL_GPL(m2p_add_override); |
| @@ -752,6 +771,7 @@ int m2p_remove_override(struct page *page, bool clear_pte) | |||
| 752 | unsigned long uninitialized_var(address); | 771 | unsigned long uninitialized_var(address); |
| 753 | unsigned level; | 772 | unsigned level; |
| 754 | pte_t *ptep = NULL; | 773 | pte_t *ptep = NULL; |
| 774 | int ret = 0; | ||
| 755 | 775 | ||
| 756 | pfn = page_to_pfn(page); | 776 | pfn = page_to_pfn(page); |
| 757 | mfn = get_phys_to_machine(pfn); | 777 | mfn = get_phys_to_machine(pfn); |
| @@ -821,6 +841,22 @@ int m2p_remove_override(struct page *page, bool clear_pte) | |||
| 821 | } else | 841 | } else |
| 822 | set_phys_to_machine(pfn, page->index); | 842 | set_phys_to_machine(pfn, page->index); |
| 823 | 843 | ||
| 844 | /* p2m(m2p(mfn)) == FOREIGN_FRAME(mfn): the mfn is already present | ||
| 845 | * somewhere in this domain, even before being added to the | ||
| 846 | * m2p_override (see comment above in m2p_add_override). | ||
| 847 | * If there are no other entries in the m2p_override corresponding | ||
| 848 | * to this mfn, then remove the FOREIGN_FRAME_BIT from the p2m for | ||
| 849 | * the original pfn (the one shared by the frontend): the backend | ||
| 850 | * cannot do any IO on this page anymore because it has been | ||
| 851 | * unshared. Removing the FOREIGN_FRAME_BIT from the p2m entry of | ||
| 852 | * the original pfn causes mfn_to_pfn(mfn) to return the frontend | ||
| 853 | * pfn again. */ | ||
| 854 | mfn &= ~FOREIGN_FRAME_BIT; | ||
| 855 | ret = __get_user(pfn, &machine_to_phys_mapping[mfn]); | ||
| 856 | if (ret == 0 && get_phys_to_machine(pfn) == FOREIGN_FRAME(mfn) && | ||
| 857 | m2p_find_override(mfn) == NULL) | ||
| 858 | set_phys_to_machine(pfn, mfn); | ||
| 859 | |||
| 824 | return 0; | 860 | return 0; |
| 825 | } | 861 | } |
| 826 | EXPORT_SYMBOL_GPL(m2p_remove_override); | 862 | EXPORT_SYMBOL_GPL(m2p_remove_override); |
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index 3ebba0753d38..a4790bf22c59 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c | |||
| @@ -371,7 +371,8 @@ char * __init xen_memory_setup(void) | |||
| 371 | populated = xen_populate_chunk(map, memmap.nr_entries, | 371 | populated = xen_populate_chunk(map, memmap.nr_entries, |
| 372 | max_pfn, &last_pfn, xen_released_pages); | 372 | max_pfn, &last_pfn, xen_released_pages); |
| 373 | 373 | ||
| 374 | extra_pages += (xen_released_pages - populated); | 374 | xen_released_pages -= populated; |
| 375 | extra_pages += xen_released_pages; | ||
| 375 | 376 | ||
| 376 | if (last_pfn > max_pfn) { | 377 | if (last_pfn > max_pfn) { |
| 377 | max_pfn = min(MAX_DOMAIN_PAGES, last_pfn); | 378 | max_pfn = min(MAX_DOMAIN_PAGES, last_pfn); |
diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c index d3d91dae065c..944eaeb8e0cf 100644 --- a/drivers/tty/hvc/hvc_xen.c +++ b/drivers/tty/hvc/hvc_xen.c | |||
| @@ -214,24 +214,24 @@ static int xen_hvm_console_init(void) | |||
| 214 | /* already configured */ | 214 | /* already configured */ |
| 215 | if (info->intf != NULL) | 215 | if (info->intf != NULL) |
| 216 | return 0; | 216 | return 0; |
| 217 | 217 | /* | |
| 218 | * If the toolstack (or the hypervisor) hasn't set these values, the | ||
| 219 | * default value is 0. Even though mfn = 0 and evtchn = 0 are | ||
| 220 | * theoretically correct values, in practice they never are and they | ||
| 221 | * mean that a legacy toolstack hasn't initialized the pv console correctly. | ||
| 222 | */ | ||
| 218 | r = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &v); | 223 | r = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &v); |
| 219 | if (r < 0) { | 224 | if (r < 0 || v == 0) |
| 220 | kfree(info); | 225 | goto err; |
| 221 | return -ENODEV; | ||
| 222 | } | ||
| 223 | info->evtchn = v; | 226 | info->evtchn = v; |
| 224 | hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &v); | 227 | v = 0; |
| 225 | if (r < 0) { | 228 | r = hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &v); |
| 226 | kfree(info); | 229 | if (r < 0 || v == 0) |
| 227 | return -ENODEV; | 230 | goto err; |
| 228 | } | ||
| 229 | mfn = v; | 231 | mfn = v; |
| 230 | info->intf = ioremap(mfn << PAGE_SHIFT, PAGE_SIZE); | 232 | info->intf = ioremap(mfn << PAGE_SHIFT, PAGE_SIZE); |
| 231 | if (info->intf == NULL) { | 233 | if (info->intf == NULL) |
| 232 | kfree(info); | 234 | goto err; |
| 233 | return -ENODEV; | ||
| 234 | } | ||
| 235 | info->vtermno = HVC_COOKIE; | 235 | info->vtermno = HVC_COOKIE; |
| 236 | 236 | ||
| 237 | spin_lock(&xencons_lock); | 237 | spin_lock(&xencons_lock); |
| @@ -239,6 +239,9 @@ static int xen_hvm_console_init(void) | |||
| 239 | spin_unlock(&xencons_lock); | 239 | spin_unlock(&xencons_lock); |
| 240 | 240 | ||
| 241 | return 0; | 241 | return 0; |
| 242 | err: | ||
| 243 | kfree(info); | ||
| 244 | return -ENODEV; | ||
| 242 | } | 245 | } |
| 243 | 246 | ||
| 244 | static int xen_pv_console_init(void) | 247 | static int xen_pv_console_init(void) |
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 6908e4ce2a0d..7595581d032c 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
| @@ -827,6 +827,9 @@ int bind_evtchn_to_irq(unsigned int evtchn) | |||
| 827 | handle_edge_irq, "event"); | 827 | handle_edge_irq, "event"); |
| 828 | 828 | ||
| 829 | xen_irq_info_evtchn_init(irq, evtchn); | 829 | xen_irq_info_evtchn_init(irq, evtchn); |
| 830 | } else { | ||
| 831 | struct irq_info *info = info_for_irq(irq); | ||
| 832 | WARN_ON(info == NULL || info->type != IRQT_EVTCHN); | ||
| 830 | } | 833 | } |
| 831 | 834 | ||
| 832 | out: | 835 | out: |
| @@ -862,6 +865,9 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) | |||
| 862 | xen_irq_info_ipi_init(cpu, irq, evtchn, ipi); | 865 | xen_irq_info_ipi_init(cpu, irq, evtchn, ipi); |
| 863 | 866 | ||
| 864 | bind_evtchn_to_cpu(evtchn, cpu); | 867 | bind_evtchn_to_cpu(evtchn, cpu); |
| 868 | } else { | ||
| 869 | struct irq_info *info = info_for_irq(irq); | ||
| 870 | WARN_ON(info == NULL || info->type != IRQT_IPI); | ||
| 865 | } | 871 | } |
| 866 | 872 | ||
| 867 | out: | 873 | out: |
| @@ -939,6 +945,9 @@ int bind_virq_to_irq(unsigned int virq, unsigned int cpu) | |||
| 939 | xen_irq_info_virq_init(cpu, irq, evtchn, virq); | 945 | xen_irq_info_virq_init(cpu, irq, evtchn, virq); |
| 940 | 946 | ||
| 941 | bind_evtchn_to_cpu(evtchn, cpu); | 947 | bind_evtchn_to_cpu(evtchn, cpu); |
| 948 | } else { | ||
| 949 | struct irq_info *info = info_for_irq(irq); | ||
| 950 | WARN_ON(info == NULL || info->type != IRQT_VIRQ); | ||
| 942 | } | 951 | } |
| 943 | 952 | ||
| 944 | out: | 953 | out: |
diff --git a/drivers/xen/pci.c b/drivers/xen/pci.c index b84bf0b6cc34..18fff88254eb 100644 --- a/drivers/xen/pci.c +++ b/drivers/xen/pci.c | |||
| @@ -59,7 +59,7 @@ static int xen_add_device(struct device *dev) | |||
| 59 | 59 | ||
| 60 | #ifdef CONFIG_ACPI | 60 | #ifdef CONFIG_ACPI |
| 61 | handle = DEVICE_ACPI_HANDLE(&pci_dev->dev); | 61 | handle = DEVICE_ACPI_HANDLE(&pci_dev->dev); |
| 62 | if (!handle) | 62 | if (!handle && pci_dev->bus->bridge) |
| 63 | handle = DEVICE_ACPI_HANDLE(pci_dev->bus->bridge); | 63 | handle = DEVICE_ACPI_HANDLE(pci_dev->bus->bridge); |
| 64 | #ifdef CONFIG_PCI_IOV | 64 | #ifdef CONFIG_PCI_IOV |
| 65 | if (!handle && pci_dev->is_virtfn) | 65 | if (!handle && pci_dev->is_virtfn) |
