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) |