Bug-fixes:
* Fix M2P batching re-using the incorrect structure field. * Disable BIOS SMP MP table search. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQEcBAABAgAGBQJQXGfdAAoJEFjIrFwIi8fJbWcH/0FI2d/VyB+ZU0ng3R0Oa7mt iR/x+Z+mfFdp2dXS6gs6DgJIZVA7i2K9pX4rOXjpDGGGyUeo1xoqjlQfsFWQGjZ/ p49RrDrM93c2GdRXk3iMSWfboQI7BXBs5rnyYZQL7kMxUSR75MxbeONvhPrMSO9I 3EBidWH08qjrn2HVF44F6xh5ONjpclo5AvGIzJ0eU4X0D0eqMnhvlAw8/UYJU2HV heRvuxWF9l2jNpLhKhZy1730D1X/vKA5qKAcBW8rCOpEijyPpmtKbqapeUJg/9pH NVquuwGutP5ozrSi7a/23+L+ezvQBmCPm5ZRG44PccBoZ/HVs8haT8UypSWSDzo= =TwvM -----END PGP SIGNATURE----- Merge tag 'stable/for-linus-3.6-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen Pull Xen bug-fixes from Konrad Rzeszutek Wilk: - Fix M2P batching re-using the incorrect structure field. In v3.5 we added batching for M2P override (Machine Frame Number -> Physical Frame Number), but the original MFN was saved in an incorrect structure - and we would oops/restore when restoring with the old MFN. - Disable BIOS SMP MP table search. A bootup issue that we had ignored until we found that on DL380 G6 it was needed. * tag 'stable/for-linus-3.6-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen: xen/boot: Disable BIOS SMP MP table search. xen/m2p: do not reuse kmap_op->dev_bus_addr
This commit is contained in:
commit
8ca7de9164
7 changed files with 27 additions and 23 deletions
|
@ -51,7 +51,8 @@ extern unsigned long set_phys_range_identity(unsigned long pfn_s,
|
||||||
|
|
||||||
extern int m2p_add_override(unsigned long mfn, struct page *page,
|
extern int m2p_add_override(unsigned long mfn, struct page *page,
|
||||||
struct gnttab_map_grant_ref *kmap_op);
|
struct gnttab_map_grant_ref *kmap_op);
|
||||||
extern int m2p_remove_override(struct page *page, bool clear_pte);
|
extern int m2p_remove_override(struct page *page,
|
||||||
|
struct gnttab_map_grant_ref *kmap_op);
|
||||||
extern struct page *m2p_find_override(unsigned long mfn);
|
extern struct page *m2p_find_override(unsigned long mfn);
|
||||||
extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn);
|
extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn);
|
||||||
|
|
||||||
|
|
|
@ -1452,6 +1452,10 @@ asmlinkage void __init xen_start_kernel(void)
|
||||||
pci_request_acs();
|
pci_request_acs();
|
||||||
|
|
||||||
xen_acpi_sleep_register();
|
xen_acpi_sleep_register();
|
||||||
|
|
||||||
|
/* Avoid searching for BIOS MP tables */
|
||||||
|
x86_init.mpparse.find_smp_config = x86_init_noop;
|
||||||
|
x86_init.mpparse.get_smp_config = x86_init_uint_noop;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_PCI
|
#ifdef CONFIG_PCI
|
||||||
/* PCI BIOS service won't work from a PV guest. */
|
/* PCI BIOS service won't work from a PV guest. */
|
||||||
|
|
|
@ -828,9 +828,6 @@ int m2p_add_override(unsigned long mfn, struct page *page,
|
||||||
|
|
||||||
xen_mc_issue(PARAVIRT_LAZY_MMU);
|
xen_mc_issue(PARAVIRT_LAZY_MMU);
|
||||||
}
|
}
|
||||||
/* let's use dev_bus_addr to record the old mfn instead */
|
|
||||||
kmap_op->dev_bus_addr = page->index;
|
|
||||||
page->index = (unsigned long) kmap_op;
|
|
||||||
}
|
}
|
||||||
spin_lock_irqsave(&m2p_override_lock, flags);
|
spin_lock_irqsave(&m2p_override_lock, flags);
|
||||||
list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]);
|
list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]);
|
||||||
|
@ -857,7 +854,8 @@ int m2p_add_override(unsigned long mfn, struct page *page,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(m2p_add_override);
|
EXPORT_SYMBOL_GPL(m2p_add_override);
|
||||||
int m2p_remove_override(struct page *page, bool clear_pte)
|
int m2p_remove_override(struct page *page,
|
||||||
|
struct gnttab_map_grant_ref *kmap_op)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned long mfn;
|
unsigned long mfn;
|
||||||
|
@ -887,10 +885,8 @@ int m2p_remove_override(struct page *page, bool clear_pte)
|
||||||
WARN_ON(!PagePrivate(page));
|
WARN_ON(!PagePrivate(page));
|
||||||
ClearPagePrivate(page);
|
ClearPagePrivate(page);
|
||||||
|
|
||||||
if (clear_pte) {
|
set_phys_to_machine(pfn, page->index);
|
||||||
struct gnttab_map_grant_ref *map_op =
|
if (kmap_op != NULL) {
|
||||||
(struct gnttab_map_grant_ref *) page->index;
|
|
||||||
set_phys_to_machine(pfn, map_op->dev_bus_addr);
|
|
||||||
if (!PageHighMem(page)) {
|
if (!PageHighMem(page)) {
|
||||||
struct multicall_space mcs;
|
struct multicall_space mcs;
|
||||||
struct gnttab_unmap_grant_ref *unmap_op;
|
struct gnttab_unmap_grant_ref *unmap_op;
|
||||||
|
@ -902,13 +898,13 @@ int m2p_remove_override(struct page *page, bool clear_pte)
|
||||||
* issued. In this case handle is going to -1 because
|
* issued. In this case handle is going to -1 because
|
||||||
* it hasn't been modified yet.
|
* it hasn't been modified yet.
|
||||||
*/
|
*/
|
||||||
if (map_op->handle == -1)
|
if (kmap_op->handle == -1)
|
||||||
xen_mc_flush();
|
xen_mc_flush();
|
||||||
/*
|
/*
|
||||||
* Now if map_op->handle is negative it means that the
|
* Now if kmap_op->handle is negative it means that the
|
||||||
* hypercall actually returned an error.
|
* hypercall actually returned an error.
|
||||||
*/
|
*/
|
||||||
if (map_op->handle == GNTST_general_error) {
|
if (kmap_op->handle == GNTST_general_error) {
|
||||||
printk(KERN_WARNING "m2p_remove_override: "
|
printk(KERN_WARNING "m2p_remove_override: "
|
||||||
"pfn %lx mfn %lx, failed to modify kernel mappings",
|
"pfn %lx mfn %lx, failed to modify kernel mappings",
|
||||||
pfn, mfn);
|
pfn, mfn);
|
||||||
|
@ -918,8 +914,8 @@ int m2p_remove_override(struct page *page, bool clear_pte)
|
||||||
mcs = xen_mc_entry(
|
mcs = xen_mc_entry(
|
||||||
sizeof(struct gnttab_unmap_grant_ref));
|
sizeof(struct gnttab_unmap_grant_ref));
|
||||||
unmap_op = mcs.args;
|
unmap_op = mcs.args;
|
||||||
unmap_op->host_addr = map_op->host_addr;
|
unmap_op->host_addr = kmap_op->host_addr;
|
||||||
unmap_op->handle = map_op->handle;
|
unmap_op->handle = kmap_op->handle;
|
||||||
unmap_op->dev_bus_addr = 0;
|
unmap_op->dev_bus_addr = 0;
|
||||||
|
|
||||||
MULTI_grant_table_op(mcs.mc,
|
MULTI_grant_table_op(mcs.mc,
|
||||||
|
@ -930,10 +926,9 @@ int m2p_remove_override(struct page *page, bool clear_pte)
|
||||||
set_pte_at(&init_mm, address, ptep,
|
set_pte_at(&init_mm, address, ptep,
|
||||||
pfn_pte(pfn, PAGE_KERNEL));
|
pfn_pte(pfn, PAGE_KERNEL));
|
||||||
__flush_tlb_single(address);
|
__flush_tlb_single(address);
|
||||||
map_op->host_addr = 0;
|
kmap_op->host_addr = 0;
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
set_phys_to_machine(pfn, page->index);
|
|
||||||
|
|
||||||
/* p2m(m2p(mfn)) == FOREIGN_FRAME(mfn): the mfn is already present
|
/* p2m(m2p(mfn)) == FOREIGN_FRAME(mfn): the mfn is already present
|
||||||
* somewhere in this domain, even before being added to the
|
* somewhere in this domain, even before being added to the
|
||||||
|
|
|
@ -337,7 +337,7 @@ static void xen_blkbk_unmap(struct pending_req *req)
|
||||||
invcount++;
|
invcount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = gnttab_unmap_refs(unmap, pages, invcount, false);
|
ret = gnttab_unmap_refs(unmap, NULL, pages, invcount);
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -314,8 +314,9 @@ static int __unmap_grant_pages(struct grant_map *map, int offset, int pages)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = gnttab_unmap_refs(map->unmap_ops + offset, map->pages + offset,
|
err = gnttab_unmap_refs(map->unmap_ops + offset,
|
||||||
pages, true);
|
use_ptemod ? map->kmap_ops + offset : NULL, map->pages + offset,
|
||||||
|
pages);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
|
|
@ -870,7 +870,8 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
|
||||||
EXPORT_SYMBOL_GPL(gnttab_map_refs);
|
EXPORT_SYMBOL_GPL(gnttab_map_refs);
|
||||||
|
|
||||||
int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
|
int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
|
||||||
struct page **pages, unsigned int count, bool clear_pte)
|
struct gnttab_map_grant_ref *kmap_ops,
|
||||||
|
struct page **pages, unsigned int count)
|
||||||
{
|
{
|
||||||
int i, ret;
|
int i, ret;
|
||||||
bool lazy = false;
|
bool lazy = false;
|
||||||
|
@ -888,7 +889,8 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
ret = m2p_remove_override(pages[i], clear_pte);
|
ret = m2p_remove_override(pages[i], kmap_ops ?
|
||||||
|
&kmap_ops[i] : NULL);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,6 +187,7 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
|
||||||
struct gnttab_map_grant_ref *kmap_ops,
|
struct gnttab_map_grant_ref *kmap_ops,
|
||||||
struct page **pages, unsigned int count);
|
struct page **pages, unsigned int count);
|
||||||
int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
|
int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
|
||||||
struct page **pages, unsigned int count, bool clear_pte);
|
struct gnttab_map_grant_ref *kunmap_ops,
|
||||||
|
struct page **pages, unsigned int count);
|
||||||
|
|
||||||
#endif /* __ASM_GNTTAB_H__ */
|
#endif /* __ASM_GNTTAB_H__ */
|
||||||
|
|
Loading…
Add table
Reference in a new issue