aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/xen
diff options
context:
space:
mode:
authorDavid Vrabel <david.vrabel@citrix.com>2015-01-05 12:06:01 -0500
committerDavid Vrabel <david.vrabel@citrix.com>2015-01-28 09:03:10 -0500
commit0bb599fd30108883b00c7d4a226eeb49111e6932 (patch)
treee7939c55ff9b95a2eb180884bea213c1b78eb863 /arch/x86/xen
parent853d0289340026b30f93fd0e768340221d4e605c (diff)
xen: remove scratch frames for ballooned pages and m2p override
The scratch frame mappings for ballooned pages and the m2p override are broken. Remove them in preparation for replacing them with simpler mechanisms that works. The scratch pages did not ensure that the page was not in use. In particular, the foreign page could still be in use by hardware. If the guest reused the frame the hardware could read or write that frame. The m2p override did not handle the same frame being granted by two different grant references. Trying an M2P override lookup in this case is impossible. With the m2p override removed, the grant map/unmap for the kernel mappings (for x86 PV) can be easily batched in set_foreign_p2m_mapping() and clear_foreign_p2m_mapping(). Signed-off-by: David Vrabel <david.vrabel@citrix.com> Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Diffstat (limited to 'arch/x86/xen')
-rw-r--r--arch/x86/xen/p2m.c254
1 files changed, 8 insertions, 246 deletions
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c
index df40b2888eae..c9bc53f64359 100644
--- a/arch/x86/xen/p2m.c
+++ b/arch/x86/xen/p2m.c
@@ -84,8 +84,6 @@
84 84
85#define PMDS_PER_MID_PAGE (P2M_MID_PER_PAGE / PTRS_PER_PTE) 85#define PMDS_PER_MID_PAGE (P2M_MID_PER_PAGE / PTRS_PER_PTE)
86 86
87static void __init m2p_override_init(void);
88
89unsigned long *xen_p2m_addr __read_mostly; 87unsigned long *xen_p2m_addr __read_mostly;
90EXPORT_SYMBOL_GPL(xen_p2m_addr); 88EXPORT_SYMBOL_GPL(xen_p2m_addr);
91unsigned long xen_p2m_size __read_mostly; 89unsigned long xen_p2m_size __read_mostly;
@@ -402,8 +400,6 @@ void __init xen_vmalloc_p2m_tree(void)
402 xen_p2m_size = xen_max_p2m_pfn; 400 xen_p2m_size = xen_max_p2m_pfn;
403 401
404 xen_inv_extra_mem(); 402 xen_inv_extra_mem();
405
406 m2p_override_init();
407} 403}
408 404
409unsigned long get_phys_to_machine(unsigned long pfn) 405unsigned long get_phys_to_machine(unsigned long pfn)
@@ -652,100 +648,21 @@ bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
652 return true; 648 return true;
653} 649}
654 650
655#define M2P_OVERRIDE_HASH_SHIFT 10
656#define M2P_OVERRIDE_HASH (1 << M2P_OVERRIDE_HASH_SHIFT)
657
658static struct list_head *m2p_overrides;
659static DEFINE_SPINLOCK(m2p_override_lock);
660
661static void __init m2p_override_init(void)
662{
663 unsigned i;
664
665 m2p_overrides = alloc_bootmem_align(
666 sizeof(*m2p_overrides) * M2P_OVERRIDE_HASH,
667 sizeof(unsigned long));
668
669 for (i = 0; i < M2P_OVERRIDE_HASH; i++)
670 INIT_LIST_HEAD(&m2p_overrides[i]);
671}
672
673static unsigned long mfn_hash(unsigned long mfn)
674{
675 return hash_long(mfn, M2P_OVERRIDE_HASH_SHIFT);
676}
677
678/* Add an MFN override for a particular page */
679static int m2p_add_override(unsigned long mfn, struct page *page,
680 struct gnttab_map_grant_ref *kmap_op)
681{
682 unsigned long flags;
683 unsigned long pfn;
684 unsigned long uninitialized_var(address);
685 unsigned level;
686 pte_t *ptep = NULL;
687
688 pfn = page_to_pfn(page);
689 if (!PageHighMem(page)) {
690 address = (unsigned long)__va(pfn << PAGE_SHIFT);
691 ptep = lookup_address(address, &level);
692 if (WARN(ptep == NULL || level != PG_LEVEL_4K,
693 "m2p_add_override: pfn %lx not mapped", pfn))
694 return -EINVAL;
695 }
696
697 if (kmap_op != NULL) {
698 if (!PageHighMem(page)) {
699 struct multicall_space mcs =
700 xen_mc_entry(sizeof(*kmap_op));
701
702 MULTI_grant_table_op(mcs.mc,
703 GNTTABOP_map_grant_ref, kmap_op, 1);
704
705 xen_mc_issue(PARAVIRT_LAZY_MMU);
706 }
707 }
708 spin_lock_irqsave(&m2p_override_lock, flags);
709 list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]);
710 spin_unlock_irqrestore(&m2p_override_lock, flags);
711
712 /* p2m(m2p(mfn)) == mfn: the mfn is already present somewhere in
713 * this domain. Set the FOREIGN_FRAME_BIT in the p2m for the other
714 * pfn so that the following mfn_to_pfn(mfn) calls will return the
715 * pfn from the m2p_override (the backend pfn) instead.
716 * We need to do this because the pages shared by the frontend
717 * (xen-blkfront) can be already locked (lock_page, called by
718 * do_read_cache_page); when the userspace backend tries to use them
719 * with direct_IO, mfn_to_pfn returns the pfn of the frontend, so
720 * do_blockdev_direct_IO is going to try to lock the same pages
721 * again resulting in a deadlock.
722 * As a side effect get_user_pages_fast might not be safe on the
723 * frontend pages while they are being shared with the backend,
724 * because mfn_to_pfn (that ends up being called by GUPF) will
725 * return the backend pfn rather than the frontend pfn. */
726 pfn = mfn_to_pfn_no_overrides(mfn);
727 if (__pfn_to_mfn(pfn) == mfn)
728 set_phys_to_machine(pfn, FOREIGN_FRAME(mfn));
729
730 return 0;
731}
732
733int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops, 651int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops,
734 struct gnttab_map_grant_ref *kmap_ops, 652 struct gnttab_map_grant_ref *kmap_ops,
735 struct page **pages, unsigned int count) 653 struct page **pages, unsigned int count)
736{ 654{
737 int i, ret = 0; 655 int i, ret = 0;
738 bool lazy = false;
739 pte_t *pte; 656 pte_t *pte;
740 657
741 if (xen_feature(XENFEAT_auto_translated_physmap)) 658 if (xen_feature(XENFEAT_auto_translated_physmap))
742 return 0; 659 return 0;
743 660
744 if (kmap_ops && 661 if (kmap_ops) {
745 !in_interrupt() && 662 ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
746 paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) { 663 kmap_ops, count);
747 arch_enter_lazy_mmu_mode(); 664 if (ret)
748 lazy = true; 665 goto out;
749 } 666 }
750 667
751 for (i = 0; i < count; i++) { 668 for (i = 0; i < count; i++) {
@@ -773,160 +690,22 @@ int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops,
773 ret = -ENOMEM; 690 ret = -ENOMEM;
774 goto out; 691 goto out;
775 } 692 }
776
777 if (kmap_ops) {
778 ret = m2p_add_override(mfn, pages[i], &kmap_ops[i]);
779 if (ret)
780 goto out;
781 }
782 } 693 }
783 694
784out: 695out:
785 if (lazy)
786 arch_leave_lazy_mmu_mode();
787
788 return ret; 696 return ret;
789} 697}
790EXPORT_SYMBOL_GPL(set_foreign_p2m_mapping); 698EXPORT_SYMBOL_GPL(set_foreign_p2m_mapping);
791 699
792static struct page *m2p_find_override(unsigned long mfn)
793{
794 unsigned long flags;
795 struct list_head *bucket;
796 struct page *p, *ret;
797
798 if (unlikely(!m2p_overrides))
799 return NULL;
800
801 ret = NULL;
802 bucket = &m2p_overrides[mfn_hash(mfn)];
803
804 spin_lock_irqsave(&m2p_override_lock, flags);
805
806 list_for_each_entry(p, bucket, lru) {
807 if (page_private(p) == mfn) {
808 ret = p;
809 break;
810 }
811 }
812
813 spin_unlock_irqrestore(&m2p_override_lock, flags);
814
815 return ret;
816}
817
818static int m2p_remove_override(struct page *page,
819 struct gnttab_unmap_grant_ref *kunmap_op,
820 unsigned long mfn)
821{
822 unsigned long flags;
823 unsigned long pfn;
824 unsigned long uninitialized_var(address);
825 unsigned level;
826 pte_t *ptep = NULL;
827
828 pfn = page_to_pfn(page);
829
830 if (!PageHighMem(page)) {
831 address = (unsigned long)__va(pfn << PAGE_SHIFT);
832 ptep = lookup_address(address, &level);
833
834 if (WARN(ptep == NULL || level != PG_LEVEL_4K,
835 "m2p_remove_override: pfn %lx not mapped", pfn))
836 return -EINVAL;
837 }
838
839 spin_lock_irqsave(&m2p_override_lock, flags);
840 list_del(&page->lru);
841 spin_unlock_irqrestore(&m2p_override_lock, flags);
842
843 if (kunmap_op != NULL) {
844 if (!PageHighMem(page)) {
845 struct multicall_space mcs;
846 struct gnttab_unmap_and_replace *unmap_op;
847 struct page *scratch_page = get_balloon_scratch_page();
848 unsigned long scratch_page_address = (unsigned long)
849 __va(page_to_pfn(scratch_page) << PAGE_SHIFT);
850
851 /*
852 * It might be that we queued all the m2p grant table
853 * hypercalls in a multicall, then m2p_remove_override
854 * get called before the multicall has actually been
855 * issued. In this case handle is going to -1 because
856 * it hasn't been modified yet.
857 */
858 if (kunmap_op->handle == -1)
859 xen_mc_flush();
860 /*
861 * Now if kmap_op->handle is negative it means that the
862 * hypercall actually returned an error.
863 */
864 if (kunmap_op->handle == GNTST_general_error) {
865 pr_warn("m2p_remove_override: pfn %lx mfn %lx, failed to modify kernel mappings",
866 pfn, mfn);
867 put_balloon_scratch_page();
868 return -1;
869 }
870
871 xen_mc_batch();
872
873 mcs = __xen_mc_entry(
874 sizeof(struct gnttab_unmap_and_replace));
875 unmap_op = mcs.args;
876 unmap_op->host_addr = kunmap_op->host_addr;
877 unmap_op->new_addr = scratch_page_address;
878 unmap_op->handle = kunmap_op->handle;
879
880 MULTI_grant_table_op(mcs.mc,
881 GNTTABOP_unmap_and_replace, unmap_op, 1);
882
883 mcs = __xen_mc_entry(0);
884 MULTI_update_va_mapping(mcs.mc, scratch_page_address,
885 pfn_pte(page_to_pfn(scratch_page),
886 PAGE_KERNEL_RO), 0);
887
888 xen_mc_issue(PARAVIRT_LAZY_MMU);
889
890 put_balloon_scratch_page();
891 }
892 }
893
894 /* p2m(m2p(mfn)) == FOREIGN_FRAME(mfn): the mfn is already present
895 * somewhere in this domain, even before being added to the
896 * m2p_override (see comment above in m2p_add_override).
897 * If there are no other entries in the m2p_override corresponding
898 * to this mfn, then remove the FOREIGN_FRAME_BIT from the p2m for
899 * the original pfn (the one shared by the frontend): the backend
900 * cannot do any IO on this page anymore because it has been
901 * unshared. Removing the FOREIGN_FRAME_BIT from the p2m entry of
902 * the original pfn causes mfn_to_pfn(mfn) to return the frontend
903 * pfn again. */
904 mfn &= ~FOREIGN_FRAME_BIT;
905 pfn = mfn_to_pfn_no_overrides(mfn);
906 if (__pfn_to_mfn(pfn) == FOREIGN_FRAME(mfn) &&
907 m2p_find_override(mfn) == NULL)
908 set_phys_to_machine(pfn, mfn);
909
910 return 0;
911}
912
913int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops, 700int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops,
914 struct gnttab_unmap_grant_ref *kunmap_ops, 701 struct gnttab_unmap_grant_ref *kunmap_ops,
915 struct page **pages, unsigned int count) 702 struct page **pages, unsigned int count)
916{ 703{
917 int i, ret = 0; 704 int i, ret = 0;
918 bool lazy = false;
919 705
920 if (xen_feature(XENFEAT_auto_translated_physmap)) 706 if (xen_feature(XENFEAT_auto_translated_physmap))
921 return 0; 707 return 0;
922 708
923 if (kunmap_ops &&
924 !in_interrupt() &&
925 paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) {
926 arch_enter_lazy_mmu_mode();
927 lazy = true;
928 }
929
930 for (i = 0; i < count; i++) { 709 for (i = 0; i < count; i++) {
931 unsigned long mfn = __pfn_to_mfn(page_to_pfn(pages[i])); 710 unsigned long mfn = __pfn_to_mfn(page_to_pfn(pages[i]));
932 unsigned long pfn = page_to_pfn(pages[i]); 711 unsigned long pfn = page_to_pfn(pages[i]);
@@ -940,32 +719,15 @@ int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops,
940 WARN_ON(!PagePrivate(pages[i])); 719 WARN_ON(!PagePrivate(pages[i]));
941 ClearPagePrivate(pages[i]); 720 ClearPagePrivate(pages[i]);
942 set_phys_to_machine(pfn, pages[i]->index); 721 set_phys_to_machine(pfn, pages[i]->index);
943
944 if (kunmap_ops)
945 ret = m2p_remove_override(pages[i], &kunmap_ops[i], mfn);
946 if (ret)
947 goto out;
948 } 722 }
949 723 if (kunmap_ops)
724 ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
725 kunmap_ops, count);
950out: 726out:
951 if (lazy)
952 arch_leave_lazy_mmu_mode();
953 return ret; 727 return ret;
954} 728}
955EXPORT_SYMBOL_GPL(clear_foreign_p2m_mapping); 729EXPORT_SYMBOL_GPL(clear_foreign_p2m_mapping);
956 730
957unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn)
958{
959 struct page *p = m2p_find_override(mfn);
960 unsigned long ret = pfn;
961
962 if (p)
963 ret = page_to_pfn(p);
964
965 return ret;
966}
967EXPORT_SYMBOL_GPL(m2p_find_override_pfn);
968
969#ifdef CONFIG_XEN_DEBUG_FS 731#ifdef CONFIG_XEN_DEBUG_FS
970#include <linux/debugfs.h> 732#include <linux/debugfs.h>
971#include "debugfs.h" 733#include "debugfs.h"