Commit 8ca7de91 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'stable/for-linus-3.6-rc6-tag' of...

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
parents e05e279e bd49940a
...@@ -51,7 +51,8 @@ extern unsigned long set_phys_range_identity(unsigned long pfn_s, ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment