diff options
-rw-r--r-- | arch/x86/include/asm/xen/page.h | 5 | ||||
-rw-r--r-- | arch/x86/xen/p2m.c | 10 | ||||
-rw-r--r-- | drivers/xen/grant-table.c | 31 |
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); | |||
47 | extern unsigned long set_phys_range_identity(unsigned long pfn_s, | 47 | extern unsigned long set_phys_range_identity(unsigned long pfn_s, |
48 | unsigned long pfn_e); | 48 | unsigned long pfn_e); |
49 | 49 | ||
50 | extern int m2p_add_override(unsigned long mfn, struct page *page); | 50 | extern int m2p_add_override(unsigned long mfn, struct page *page, |
51 | extern int m2p_remove_override(struct page *page); | 51 | bool clear_pte); |
52 | extern int m2p_remove_override(struct page *page, bool clear_pte); | ||
52 | extern struct page *m2p_find_override(unsigned long mfn); | 53 | extern struct page *m2p_find_override(unsigned long mfn); |
53 | extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn); | 54 | extern 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 */ |
653 | int m2p_add_override(unsigned long mfn, struct page *page) | 653 | int 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 | ||
688 | int m2p_remove_override(struct page *page) | 686 | int 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 | } |