forked from Minki/linux
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
@ -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,
|
||||
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 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();
|
||||
|
||||
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
|
||||
/* 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);
|
||||
}
|
||||
/* 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);
|
||||
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;
|
||||
}
|
||||
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 mfn;
|
||||
@ -887,10 +885,8 @@ int m2p_remove_override(struct page *page, bool clear_pte)
|
||||
WARN_ON(!PagePrivate(page));
|
||||
ClearPagePrivate(page);
|
||||
|
||||
if (clear_pte) {
|
||||
struct gnttab_map_grant_ref *map_op =
|
||||
(struct gnttab_map_grant_ref *) page->index;
|
||||
set_phys_to_machine(pfn, map_op->dev_bus_addr);
|
||||
set_phys_to_machine(pfn, page->index);
|
||||
if (kmap_op != NULL) {
|
||||
if (!PageHighMem(page)) {
|
||||
struct multicall_space mcs;
|
||||
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
|
||||
* it hasn't been modified yet.
|
||||
*/
|
||||
if (map_op->handle == -1)
|
||||
if (kmap_op->handle == -1)
|
||||
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.
|
||||
*/
|
||||
if (map_op->handle == GNTST_general_error) {
|
||||
if (kmap_op->handle == GNTST_general_error) {
|
||||
printk(KERN_WARNING "m2p_remove_override: "
|
||||
"pfn %lx mfn %lx, failed to modify kernel mappings",
|
||||
pfn, mfn);
|
||||
@ -918,8 +914,8 @@ int m2p_remove_override(struct page *page, bool clear_pte)
|
||||
mcs = xen_mc_entry(
|
||||
sizeof(struct gnttab_unmap_grant_ref));
|
||||
unmap_op = mcs.args;
|
||||
unmap_op->host_addr = map_op->host_addr;
|
||||
unmap_op->handle = map_op->handle;
|
||||
unmap_op->host_addr = kmap_op->host_addr;
|
||||
unmap_op->handle = kmap_op->handle;
|
||||
unmap_op->dev_bus_addr = 0;
|
||||
|
||||
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,
|
||||
pfn_pte(pfn, PAGE_KERNEL));
|
||||
__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
|
||||
* somewhere in this domain, even before being added to the
|
||||
|
@ -337,7 +337,7 @@ static void xen_blkbk_unmap(struct pending_req *req)
|
||||
invcount++;
|
||||
}
|
||||
|
||||
ret = gnttab_unmap_refs(unmap, pages, invcount, false);
|
||||
ret = gnttab_unmap_refs(unmap, NULL, pages, invcount);
|
||||
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,
|
||||
pages, true);
|
||||
err = gnttab_unmap_refs(map->unmap_ops + offset,
|
||||
use_ptemod ? map->kmap_ops + offset : NULL, map->pages + offset,
|
||||
pages);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -870,7 +870,8 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
|
||||
EXPORT_SYMBOL_GPL(gnttab_map_refs);
|
||||
|
||||
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;
|
||||
bool lazy = false;
|
||||
@ -888,7 +889,8 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
|
||||
}
|
||||
|
||||
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)
|
||||
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 page **pages, unsigned int count);
|
||||
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__ */
|
||||
|
Loading…
Reference in New Issue
Block a user