Commit 2fc136ee authored by Stefano Stabellini's avatar Stefano Stabellini Committed by Konrad Rzeszutek Wilk

xen/m2p: do not reuse kmap_op->dev_bus_addr

If the caller passes a valid kmap_op to m2p_add_override, we use
kmap_op->dev_bus_addr to store the original mfn, but dev_bus_addr is
part of the interface with Xen and if we are batching the hypercalls it
might not have been written by the hypervisor yet. That means that later
on Xen will write to it and we'll think that the original mfn is
actually what Xen has written to it.

Rather than "stealing" struct members from kmap_op, keep using
page->index to store the original mfn and add another parameter to
m2p_remove_override to get the corresponding kmap_op instead.
It is now responsibility of the caller to keep track of which kmap_op
corresponds to a particular page in the m2p_override (gntdev, the only
user of this interface that passes a valid kmap_op, is already doing that).

CC: stable@kernel.org
Reported-and-Tested-By: default avatarSander Eikelenboom <linux@eikelenboom.it>
Signed-off-by: default avatarStefano Stabellini <stefano.stabellini@eu.citrix.com>
Signed-off-by: default avatarKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
parent 80ba77df
...@@ -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);
......
...@@ -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