Five bug-fixes:
- When booting as PVHVM we would try to use PV console - but would not validate the parameters causing us to crash during restore b/c we re-use the wrong event channel. - When booting on machines with SR-IOV PCI bridge we didn't check for the bridge and tried to use it. - Under AMD machines would advertise the APERFMPERF resulting in needless amount of MSRs from the guest. - A global value (xen_released_pages) was not subtracted at bootup when pages were added back in. This resulted in the balloon worker having the wrong account of how many pages were truly released. - Fix dead-lock when xen-blkfront is run in the same domain as xen-blkback. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQEcBAABAgAGBQJP2kcmAAoJEFjIrFwIi8fJXLcH/0a2m6KMcyjc4WaCHspAEFDL 9B055QUFDEOlH55wE2QeED/8D+0HUbTYnQBycH126XLKzLfRv1fsrKFKDSA/SWW2 Mh8N316UrY5Wc3KMdxXdCXJCDqDs7VhARTv6JdlUqUlH9oLRYE6CMRO8MujT0iwd r+uEnNuW0udMFt8x9SnJW7pEaq7u2N5koEGdWEzZhfoumDaCRxm5OKAKXZ0DZlEZ /BPjTW/N+Pf4u+bJZY+wQq41y4zGMqu7TDo/hOpuGZxeqtVnCE9trBbuGLnp4K+W n4TfZZs9Y1kovSMj6qTeB0aP0F77tqHyXPb1oPKxm2kWfqT2dFtIRpuLtXYSC+o= =cQl2 -----END PGP SIGNATURE----- Merge tag 'stable/for-linus-3.5-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen Pull five Xen bug-fixes from Konrad Rzeszutek Wilk: - When booting as PVHVM we would try to use PV console - but would not validate the parameters causing us to crash during restore b/c we re-use the wrong event channel. - When booting on machines with SR-IOV PCI bridge we didn't check for the bridge and tried to use it. - Under AMD machines would advertise the APERFMPERF resulting in needless amount of MSRs from the guest. - A global value (xen_released_pages) was not subtracted at bootup when pages were added back in. This resulted in the balloon worker having the wrong account of how many pages were truly released. - Fix dead-lock when xen-blkfront is run in the same domain as xen-blkback. * tag 'stable/for-linus-3.5-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen: xen: mark local pages as FOREIGN in the m2p_override xen/setup: filter APERFMPERF cpuid feature out xen/balloon: Subtract from xen_released_pages the count that is populated. xen/pci: Check for PCI bridge before using it. xen/events: Add WARN_ON when quick lookup found invalid type. xen/hvc: Check HVM_PARAM_CONSOLE_[EVTCHN|PFN] for correctness. xen/hvc: Fix error cases around HVM_PARAM_CONSOLE_PFN xen/hvc: Collapse error logic.
This commit is contained in:
commit
069915b946
6 changed files with 73 additions and 16 deletions
|
@ -209,6 +209,9 @@ static void __init xen_banner(void)
|
|||
xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : "");
|
||||
}
|
||||
|
||||
#define CPUID_THERM_POWER_LEAF 6
|
||||
#define APERFMPERF_PRESENT 0
|
||||
|
||||
static __read_mostly unsigned int cpuid_leaf1_edx_mask = ~0;
|
||||
static __read_mostly unsigned int cpuid_leaf1_ecx_mask = ~0;
|
||||
|
||||
|
@ -242,6 +245,11 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
|
|||
*dx = cpuid_leaf5_edx_val;
|
||||
return;
|
||||
|
||||
case CPUID_THERM_POWER_LEAF:
|
||||
/* Disabling APERFMPERF for kernel usage */
|
||||
maskecx = ~(1 << APERFMPERF_PRESENT);
|
||||
break;
|
||||
|
||||
case 0xb:
|
||||
/* Suppress extended topology stuff */
|
||||
maskebx = 0;
|
||||
|
|
|
@ -706,6 +706,7 @@ int m2p_add_override(unsigned long mfn, struct page *page,
|
|||
unsigned long uninitialized_var(address);
|
||||
unsigned level;
|
||||
pte_t *ptep = NULL;
|
||||
int ret = 0;
|
||||
|
||||
pfn = page_to_pfn(page);
|
||||
if (!PageHighMem(page)) {
|
||||
|
@ -741,6 +742,24 @@ int m2p_add_override(unsigned long mfn, struct page *page,
|
|||
list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]);
|
||||
spin_unlock_irqrestore(&m2p_override_lock, flags);
|
||||
|
||||
/* p2m(m2p(mfn)) == mfn: the mfn is already present somewhere in
|
||||
* this domain. Set the FOREIGN_FRAME_BIT in the p2m for the other
|
||||
* pfn so that the following mfn_to_pfn(mfn) calls will return the
|
||||
* pfn from the m2p_override (the backend pfn) instead.
|
||||
* We need to do this because the pages shared by the frontend
|
||||
* (xen-blkfront) can be already locked (lock_page, called by
|
||||
* do_read_cache_page); when the userspace backend tries to use them
|
||||
* with direct_IO, mfn_to_pfn returns the pfn of the frontend, so
|
||||
* do_blockdev_direct_IO is going to try to lock the same pages
|
||||
* again resulting in a deadlock.
|
||||
* As a side effect get_user_pages_fast might not be safe on the
|
||||
* frontend pages while they are being shared with the backend,
|
||||
* because mfn_to_pfn (that ends up being called by GUPF) will
|
||||
* return the backend pfn rather than the frontend pfn. */
|
||||
ret = __get_user(pfn, &machine_to_phys_mapping[mfn]);
|
||||
if (ret == 0 && get_phys_to_machine(pfn) == mfn)
|
||||
set_phys_to_machine(pfn, FOREIGN_FRAME(mfn));
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(m2p_add_override);
|
||||
|
@ -752,6 +771,7 @@ int m2p_remove_override(struct page *page, bool clear_pte)
|
|||
unsigned long uninitialized_var(address);
|
||||
unsigned level;
|
||||
pte_t *ptep = NULL;
|
||||
int ret = 0;
|
||||
|
||||
pfn = page_to_pfn(page);
|
||||
mfn = get_phys_to_machine(pfn);
|
||||
|
@ -821,6 +841,22 @@ int m2p_remove_override(struct page *page, bool clear_pte)
|
|||
} else
|
||||
set_phys_to_machine(pfn, page->index);
|
||||
|
||||
/* p2m(m2p(mfn)) == FOREIGN_FRAME(mfn): the mfn is already present
|
||||
* somewhere in this domain, even before being added to the
|
||||
* m2p_override (see comment above in m2p_add_override).
|
||||
* If there are no other entries in the m2p_override corresponding
|
||||
* to this mfn, then remove the FOREIGN_FRAME_BIT from the p2m for
|
||||
* the original pfn (the one shared by the frontend): the backend
|
||||
* cannot do any IO on this page anymore because it has been
|
||||
* unshared. Removing the FOREIGN_FRAME_BIT from the p2m entry of
|
||||
* the original pfn causes mfn_to_pfn(mfn) to return the frontend
|
||||
* pfn again. */
|
||||
mfn &= ~FOREIGN_FRAME_BIT;
|
||||
ret = __get_user(pfn, &machine_to_phys_mapping[mfn]);
|
||||
if (ret == 0 && get_phys_to_machine(pfn) == FOREIGN_FRAME(mfn) &&
|
||||
m2p_find_override(mfn) == NULL)
|
||||
set_phys_to_machine(pfn, mfn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(m2p_remove_override);
|
||||
|
|
|
@ -371,7 +371,8 @@ char * __init xen_memory_setup(void)
|
|||
populated = xen_populate_chunk(map, memmap.nr_entries,
|
||||
max_pfn, &last_pfn, xen_released_pages);
|
||||
|
||||
extra_pages += (xen_released_pages - populated);
|
||||
xen_released_pages -= populated;
|
||||
extra_pages += xen_released_pages;
|
||||
|
||||
if (last_pfn > max_pfn) {
|
||||
max_pfn = min(MAX_DOMAIN_PAGES, last_pfn);
|
||||
|
|
|
@ -214,24 +214,24 @@ static int xen_hvm_console_init(void)
|
|||
/* already configured */
|
||||
if (info->intf != NULL)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If the toolstack (or the hypervisor) hasn't set these values, the
|
||||
* default value is 0. Even though mfn = 0 and evtchn = 0 are
|
||||
* theoretically correct values, in practice they never are and they
|
||||
* mean that a legacy toolstack hasn't initialized the pv console correctly.
|
||||
*/
|
||||
r = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &v);
|
||||
if (r < 0) {
|
||||
kfree(info);
|
||||
return -ENODEV;
|
||||
}
|
||||
if (r < 0 || v == 0)
|
||||
goto err;
|
||||
info->evtchn = v;
|
||||
hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &v);
|
||||
if (r < 0) {
|
||||
kfree(info);
|
||||
return -ENODEV;
|
||||
}
|
||||
v = 0;
|
||||
r = hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &v);
|
||||
if (r < 0 || v == 0)
|
||||
goto err;
|
||||
mfn = v;
|
||||
info->intf = ioremap(mfn << PAGE_SHIFT, PAGE_SIZE);
|
||||
if (info->intf == NULL) {
|
||||
kfree(info);
|
||||
return -ENODEV;
|
||||
}
|
||||
if (info->intf == NULL)
|
||||
goto err;
|
||||
info->vtermno = HVC_COOKIE;
|
||||
|
||||
spin_lock(&xencons_lock);
|
||||
|
@ -239,6 +239,9 @@ static int xen_hvm_console_init(void)
|
|||
spin_unlock(&xencons_lock);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
kfree(info);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int xen_pv_console_init(void)
|
||||
|
|
|
@ -827,6 +827,9 @@ int bind_evtchn_to_irq(unsigned int evtchn)
|
|||
handle_edge_irq, "event");
|
||||
|
||||
xen_irq_info_evtchn_init(irq, evtchn);
|
||||
} else {
|
||||
struct irq_info *info = info_for_irq(irq);
|
||||
WARN_ON(info == NULL || info->type != IRQT_EVTCHN);
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -862,6 +865,9 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
|
|||
xen_irq_info_ipi_init(cpu, irq, evtchn, ipi);
|
||||
|
||||
bind_evtchn_to_cpu(evtchn, cpu);
|
||||
} else {
|
||||
struct irq_info *info = info_for_irq(irq);
|
||||
WARN_ON(info == NULL || info->type != IRQT_IPI);
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -939,6 +945,9 @@ int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
|
|||
xen_irq_info_virq_init(cpu, irq, evtchn, virq);
|
||||
|
||||
bind_evtchn_to_cpu(evtchn, cpu);
|
||||
} else {
|
||||
struct irq_info *info = info_for_irq(irq);
|
||||
WARN_ON(info == NULL || info->type != IRQT_VIRQ);
|
||||
}
|
||||
|
||||
out:
|
||||
|
|
|
@ -59,7 +59,7 @@ static int xen_add_device(struct device *dev)
|
|||
|
||||
#ifdef CONFIG_ACPI
|
||||
handle = DEVICE_ACPI_HANDLE(&pci_dev->dev);
|
||||
if (!handle)
|
||||
if (!handle && pci_dev->bus->bridge)
|
||||
handle = DEVICE_ACPI_HANDLE(pci_dev->bus->bridge);
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
if (!handle && pci_dev->is_virtfn)
|
||||
|
|
Loading…
Reference in a new issue