]> xenbits.xensource.com Git - people/dwmw2/xen.git/commitdiff
x86/pv: Deprecate support for paging out the LDT
authorAndrew Cooper <andrew.cooper3@citrix.com>
Tue, 3 Oct 2017 10:18:37 +0000 (11:18 +0100)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Thu, 30 Aug 2018 12:38:43 +0000 (13:38 +0100)
This code is believed to be vestigial remnant of the PV Windows XP port.  It
is not used by Linux, NetBSD, Solaris or MiniOS.  Furthermore the
implementation is incomplete; it only functions for a present => not-present
transition, rather than a present => read/write transition.

The for_each_vcpu() is one scalability limitation for PV guests, which can't
reasonably be altered to be continuable.  Most importantly however, is that
this only codepath which plays with descriptor frames of a remote vcpu.

A side effect of dropping support for paging the LDT out is that the LDT no
longer automatically cleans itself up on domain destruction.  Cover this by
explicitly releasing the LDT frames at the same time as the GDT frames.

Finally, leave some asserts around to confirm the expected behaviour of all
the functions playing with PGT_seg_desc_page references.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
xen/arch/x86/Kconfig
xen/arch/x86/domain.c
xen/arch/x86/mm.c
xen/arch/x86/pv/descriptor-tables.c
xen/arch/x86/pv/domain.c
xen/arch/x86/pv/mm.c
xen/include/asm-x86/domain.h

index 73ab8f8f9fd832ba8d082daccbc7a9689bcfba25..ae1b707c198843d4d78a1ca053713443fd4110af 100644 (file)
@@ -164,3 +164,26 @@ endmenu
 source "common/Kconfig"
 
 source "drivers/Kconfig"
+
+menu "Deprecated Functionality"
+
+config PV_LDT_PAGING
+       bool "PV LDT Paging-out support"
+       depends on PV
+       ---help---
+         For a very long time, the PV ABI has included the ability to page
+         out the LDT by transitioning its mapping to not-present.  This
+         functionality is believed to only exist for the PV Windows XP port
+         which never came to anything.
+
+         The implementation contains a vCPU scalability limitation in a
+         position which is prohibitively complicated to resolve.  As the
+         feature is believed to be unused in practice, removing the feature
+         is the easiest remediation.
+
+         If you discover a usecase which is broken by this option being off,
+         please contact xen-devel@lists.xenproject.org urgently.  Baring
+         something unexpected, the code and this option will be deleted 2
+         releases after Xen 4.12.
+
+endmenu
index 4cdcd5d64c2b2d4518e433e9c1e766d06ff9a0ac..64b40c731d3501e905e96890ba1c8521e530a0a2 100644 (file)
@@ -1955,11 +1955,8 @@ int domain_relinquish_resources(struct domain *d)
         {
             for_each_vcpu ( d, v )
             {
-                /*
-                 * Relinquish GDT mappings. No need for explicit unmapping of
-                 * the LDT as it automatically gets squashed with the guest
-                 * mappings.
-                 */
+                /* Relinquish GDT/LDT mappings. */
+                pv_destroy_ldt(v);
                 pv_destroy_gdt(v);
             }
         }
index 7da9a0429b8bbf2bbbce88d3766016c666b4d0b3..84979f28d5c79e8de102c34d81fe0610bbabdb26 100644 (file)
@@ -1178,7 +1178,6 @@ void put_page_from_l1e(l1_pgentry_t l1e, struct domain *l1e_owner)
     unsigned long     pfn = l1e_get_pfn(l1e);
     struct page_info *page;
     struct domain    *pg_owner;
-    struct vcpu      *v;
 
     if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) || is_iomem_page(_mfn(pfn)) )
         return;
@@ -1219,12 +1218,14 @@ void put_page_from_l1e(l1_pgentry_t l1e, struct domain *l1e_owner)
     }
     else
     {
+#ifdef CONFIG_PV_LDT_PAGING
         /* We expect this is rare so we blow the entire shadow LDT. */
         if ( unlikely(((page->u.inuse.type_info & PGT_type_mask) ==
                        PGT_seg_desc_page)) &&
              unlikely(((page->u.inuse.type_info & PGT_count_mask) != 0)) &&
              (l1e_owner == pg_owner) )
         {
+            struct vcpu *v;
             cpumask_t *mask = this_cpu(scratch_cpumask);
 
             cpumask_clear(mask);
@@ -1243,6 +1244,7 @@ void put_page_from_l1e(l1_pgentry_t l1e, struct domain *l1e_owner)
             if ( !cpumask_empty(mask) )
                 flush_tlb_mask(mask);
         }
+#endif /* CONFIG_PV_LDT_PAGING */
         put_page(page);
     }
 }
index 9b84cbe42f61854e3bfe859a8b0b759c8ee8c3ae..8b2d55fc2ec1ec9a425cd62c40a23677ad33aa2f 100644 (file)
@@ -37,10 +37,14 @@ bool pv_destroy_ldt(struct vcpu *v)
 
     ASSERT(!in_irq());
 
+#ifdef CONFIG_PV_LDT_PAGING
     spin_lock(&v->arch.pv.shadow_ldt_lock);
 
     if ( v->arch.pv.shadow_ldt_mapcnt == 0 )
         goto out;
+#else
+    ASSERT(v == current || !vcpu_cpu_dirty(v));
+#endif
 
     pl1e = pv_ldt_ptes(v);
 
@@ -58,11 +62,13 @@ bool pv_destroy_ldt(struct vcpu *v)
         put_page_and_type(page);
     }
 
+#ifdef CONFIG_PV_LDT_PAGING
     ASSERT(v->arch.pv.shadow_ldt_mapcnt == mappings_dropped);
     v->arch.pv.shadow_ldt_mapcnt = 0;
 
  out:
     spin_unlock(&v->arch.pv.shadow_ldt_lock);
+#endif
 
     return mappings_dropped;
 }
@@ -74,6 +80,8 @@ void pv_destroy_gdt(struct vcpu *v)
     l1_pgentry_t zero_l1e = l1e_from_mfn(zero_mfn, __PAGE_HYPERVISOR_RO);
     unsigned int i;
 
+    ASSERT(v == current || !vcpu_cpu_dirty(v));
+
     v->arch.pv.gdt_ents = 0;
     for ( i = 0; i < FIRST_RESERVED_GDT_PAGE; i++ )
     {
@@ -94,6 +102,8 @@ long pv_set_gdt(struct vcpu *v, unsigned long *frames, unsigned int entries)
     l1_pgentry_t *pl1e;
     unsigned int i, nr_frames = DIV_ROUND_UP(entries, 512);
 
+    ASSERT(v == current || !vcpu_cpu_dirty(v));
+
     if ( entries > FIRST_RESERVED_GDT_ENTRY )
         return -EINVAL;
 
index ce50dacb5f7c066c3de35c56a1ad920ea3efdee0..355f320fa36cbebaa013b427e9b1ce3b02937fd6 100644 (file)
@@ -171,7 +171,9 @@ int pv_vcpu_initialise(struct vcpu *v)
 
     ASSERT(!is_idle_domain(d));
 
+#ifdef CONFIG_PV_LDT_PAGING
     spin_lock_init(&v->arch.pv.shadow_ldt_lock);
+#endif
 
     rc = pv_create_gdt_ldt_l1tab(v);
     if ( rc )
index e9156eaf4cd72c8c73a0d11bdcdc75992afb2710..f5ea00ca4eefd661e0b18a8e5d4832ffdcd2b552 100644 (file)
@@ -119,10 +119,16 @@ bool pv_map_ldt_shadow_page(unsigned int offset)
     pl1e = &pv_ldt_ptes(curr)[offset >> PAGE_SHIFT];
     l1e_add_flags(gl1e, _PAGE_RW);
 
+#ifdef CONFIG_PV_LDT_PAGING
     spin_lock(&curr->arch.pv.shadow_ldt_lock);
+#endif
+
     l1e_write(pl1e, gl1e);
+
+#ifdef CONFIG_PV_LDT_PAGING
     curr->arch.pv.shadow_ldt_mapcnt++;
     spin_unlock(&curr->arch.pv.shadow_ldt_lock);
+#endif
 
     return true;
 }
index 8eaed36d5efafea537bddb9346377fa0ffca7be3..4447088b6e8823f65d88bf59efc9a124dff2780f 100644 (file)
@@ -508,9 +508,11 @@ struct pv_vcpu
     unsigned int iopl;        /* Current IOPL for this VCPU, shifted left by
                                * 12 to match the eflags register. */
 
+#ifdef CONFIG_PV_LDT_PAGING
     /* Current LDT details. */
     unsigned long shadow_ldt_mapcnt;
     spinlock_t shadow_ldt_lock;
+#endif
 
     /* data breakpoint extension MSRs */
     uint32_t dr_mask[4];