aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/xen/page.h5
-rw-r--r--arch/x86/xen/p2m.c10
-rw-r--r--drivers/xen/grant-table.c31
3 files changed, 31 insertions, 15 deletions
diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h
index c61934fbf22a..64a619d47d34 100644
--- a/arch/x86/include/asm/xen/page.h
+++ b/arch/x86/include/asm/xen/page.h
@@ -47,8 +47,9 @@ extern bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn);
47extern unsigned long set_phys_range_identity(unsigned long pfn_s, 47extern unsigned long set_phys_range_identity(unsigned long pfn_s,
48 unsigned long pfn_e); 48 unsigned long pfn_e);
49 49
50extern int m2p_add_override(unsigned long mfn, struct page *page); 50extern int m2p_add_override(unsigned long mfn, struct page *page,
51extern int m2p_remove_override(struct page *page); 51 bool clear_pte);
52extern int m2p_remove_override(struct page *page, bool clear_pte);
52extern struct page *m2p_find_override(unsigned long mfn); 53extern struct page *m2p_find_override(unsigned long mfn);
53extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn); 54extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn);
54 55
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c
index 141eb0de8b06..2d2b32af3a1d 100644
--- a/arch/x86/xen/p2m.c
+++ b/arch/x86/xen/p2m.c
@@ -650,7 +650,7 @@ static unsigned long mfn_hash(unsigned long mfn)
650} 650}
651 651
652/* Add an MFN override for a particular page */ 652/* Add an MFN override for a particular page */
653int m2p_add_override(unsigned long mfn, struct page *page) 653int m2p_add_override(unsigned long mfn, struct page *page, bool clear_pte)
654{ 654{
655 unsigned long flags; 655 unsigned long flags;
656 unsigned long pfn; 656 unsigned long pfn;
@@ -662,7 +662,6 @@ int m2p_add_override(unsigned long mfn, struct page *page)
662 if (!PageHighMem(page)) { 662 if (!PageHighMem(page)) {
663 address = (unsigned long)__va(pfn << PAGE_SHIFT); 663 address = (unsigned long)__va(pfn << PAGE_SHIFT);
664 ptep = lookup_address(address, &level); 664 ptep = lookup_address(address, &level);
665
666 if (WARN(ptep == NULL || level != PG_LEVEL_4K, 665 if (WARN(ptep == NULL || level != PG_LEVEL_4K,
667 "m2p_add_override: pfn %lx not mapped", pfn)) 666 "m2p_add_override: pfn %lx not mapped", pfn))
668 return -EINVAL; 667 return -EINVAL;
@@ -674,10 +673,9 @@ int m2p_add_override(unsigned long mfn, struct page *page)
674 if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn)))) 673 if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn))))
675 return -ENOMEM; 674 return -ENOMEM;
676 675
677 if (!PageHighMem(page)) 676 if (clear_pte && !PageHighMem(page))
678 /* Just zap old mapping for now */ 677 /* Just zap old mapping for now */
679 pte_clear(&init_mm, address, ptep); 678 pte_clear(&init_mm, address, ptep);
680
681 spin_lock_irqsave(&m2p_override_lock, flags); 679 spin_lock_irqsave(&m2p_override_lock, flags);
682 list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]); 680 list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]);
683 spin_unlock_irqrestore(&m2p_override_lock, flags); 681 spin_unlock_irqrestore(&m2p_override_lock, flags);
@@ -685,7 +683,7 @@ int m2p_add_override(unsigned long mfn, struct page *page)
685 return 0; 683 return 0;
686} 684}
687 685
688int m2p_remove_override(struct page *page) 686int m2p_remove_override(struct page *page, bool clear_pte)
689{ 687{
690 unsigned long flags; 688 unsigned long flags;
691 unsigned long mfn; 689 unsigned long mfn;
@@ -713,7 +711,7 @@ int m2p_remove_override(struct page *page)
713 spin_unlock_irqrestore(&m2p_override_lock, flags); 711 spin_unlock_irqrestore(&m2p_override_lock, flags);
714 set_phys_to_machine(pfn, page->index); 712 set_phys_to_machine(pfn, page->index);
715 713
716 if (!PageHighMem(page)) 714 if (clear_pte && !PageHighMem(page))
717 set_pte_at(&init_mm, address, ptep, 715 set_pte_at(&init_mm, address, ptep,
718 pfn_pte(pfn, PAGE_KERNEL)); 716 pfn_pte(pfn, PAGE_KERNEL));
719 /* No tlb flush necessary because the caller already 717 /* No tlb flush necessary because the caller already
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index 3745a318defc..fd725cde6ad1 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -466,13 +466,30 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
466 if (map_ops[i].status) 466 if (map_ops[i].status)
467 continue; 467 continue;
468 468
469 /* m2p override only supported for GNTMAP_contains_pte mappings */ 469 if (map_ops[i].flags & GNTMAP_contains_pte) {
470 if (!(map_ops[i].flags & GNTMAP_contains_pte)) 470 pte = (pte_t *) (mfn_to_virt(PFN_DOWN(map_ops[i].host_addr)) +
471 continue;
472 pte = (pte_t *) (mfn_to_virt(PFN_DOWN(map_ops[i].host_addr)) +
473 (map_ops[i].host_addr & ~PAGE_MASK)); 471 (map_ops[i].host_addr & ~PAGE_MASK));
474 mfn = pte_mfn(*pte); 472 mfn = pte_mfn(*pte);
475 ret = m2p_add_override(mfn, pages[i]); 473 } else {
474 /* If you really wanted to do this:
475 * mfn = PFN_DOWN(map_ops[i].dev_bus_addr);
476 *
477 * The reason we do not implement it is b/c on the
478 * unmap path (gnttab_unmap_refs) we have no means of
479 * checking whether the page is !GNTMAP_contains_pte.
480 *
481 * That is without some extra data-structure to carry
482 * the struct page, bool clear_pte, and list_head next
483 * tuples and deal with allocation/delallocation, etc.
484 *
485 * The users of this API set the GNTMAP_contains_pte
486 * flag so lets just return not supported until it
487 * becomes neccessary to implement.
488 */
489 return -EOPNOTSUPP;
490 }
491 ret = m2p_add_override(mfn, pages[i],
492 map_ops[i].flags & GNTMAP_contains_pte);
476 if (ret) 493 if (ret)
477 return ret; 494 return ret;
478 } 495 }
@@ -494,7 +511,7 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
494 return ret; 511 return ret;
495 512
496 for (i = 0; i < count; i++) { 513 for (i = 0; i < count; i++) {
497 ret = m2p_remove_override(pages[i]); 514 ret = m2p_remove_override(pages[i], true /* clear the PTE */);
498 if (ret) 515 if (ret)
499 return ret; 516 return ret;
500 } 517 }