From: Jeremy Fitzhardinge <jeremy.fitzhardinge@xxxxxxxxxx>
When adding a page to m2p_override we change the p2m of the page so we
need to also clear the old pte of the kernel linear mapping because it
doesn't correspond anymore.
When we remove the page from m2p_override we restore the original p2m of
the page and we also restore the old pte of the kernel linear mapping.
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@xxxxxxxxxx>
Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
---
arch/x86/xen/p2m.c | 35 ++++++++++++++++++++++++++++++++++-
1 files changed, 34 insertions(+), 1 deletions(-)
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c
index 7dde8e4..ca6552d 100644
--- a/arch/x86/xen/p2m.c
+++ b/arch/x86/xen/p2m.c
@@ -29,6 +29,7 @@
#include <linux/module.h>
#include <linux/list.h>
#include <linux/hash.h>
+#include <linux/sched.h>
#include <asm/cache.h>
#include <asm/setup.h>
@@ -412,6 +413,22 @@ void m2p_add_override(unsigned long mfn, struct page *page)
page->index = pfn_to_mfn(pfn);
__set_phys_to_machine(pfn, FOREIGN_FRAME(mfn));
+ if (!PageHighMem(page)) {
+ unsigned long address = (unsigned long)__va(pfn << PAGE_SHIFT);
+ unsigned level;
+ pte_t *ptep = lookup_address(address, &level);
+
+ if (WARN(ptep == NULL || level != PG_LEVEL_4K,
+ "m2p_add_override: pfn %lx not mapped",
pfn)) {
+ __free_page(page);
+
+ return;
+ }
+
+ /* Just zap old mapping for now */
+ pte_clear(&init_mm, address, ptep);
+ }
+
spin_lock_irqsave(&m2p_override_lock, flags);
list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]);
spin_unlock_irqrestore(&m2p_override_lock, flags);
@@ -420,10 +437,26 @@ void m2p_add_override(unsigned long mfn, struct page
*page)
void m2p_remove_override(struct page *page)
{
unsigned long flags;
+ unsigned long pfn = page_to_pfn(page);
spin_lock_irqsave(&m2p_override_lock, flags);
list_del(&page->lru);
spin_unlock_irqrestore(&m2p_override_lock, flags);
- __set_phys_to_machine(page_to_pfn(page), page->index);
+ __set_phys_to_machine(pfn, page->index);
+
+ if (!PageHighMem(page)) {
+ unsigned long address = (unsigned long)__va(pfn << PAGE_SHIFT);
+ unsigned level;
+ pte_t *ptep = lookup_address(address, &level);
+
+ if (WARN(ptep == NULL || level != PG_LEVEL_4K,
+ "m2p_remove_override: pfn %lx not
mapped", pfn))
+ return;
+
+ set_pte_at(&init_mm, address, ptep,
+ pfn_pte(pfn, PAGE_KERNEL));
+ /* No tlb flush necessary because the caller already
+ * left the pte unmapped. */
+ }
}
struct page *m2p_find_override(unsigned long mfn)
--
1.5.6.5
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|