[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v2] x86/pv: Deprecate support for paging out the LDT



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@xxxxxxxxxx>
---
CC: Jan Beulich <JBeulich@xxxxxxxx>
CC: Wei Liu <wei.liu2@xxxxxxxxxx>
CC: Roger Pau Monné <roger.pau@xxxxxxxxxx>
CC: George Dunlap <George.Dunlap@xxxxxxxxxxxxx>
CC: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx>
CC: Stefano Stabellini <sstabellini@xxxxxxxxxx>
CC: Tim Deegan <tim@xxxxxxx>
CC: Julien Grall <julien.grall@xxxxxxx>

v2:
 * Make an explicit time statement, specifically avoiding second guessing the
   future naming scheme or timelines.
---
 xen/arch/x86/Kconfig                | 23 +++++++++++++++++++++++
 xen/arch/x86/domain.c               |  7 ++-----
 xen/arch/x86/mm.c                   |  4 +++-
 xen/arch/x86/pv/descriptor-tables.c | 10 ++++++++++
 xen/arch/x86/pv/domain.c            |  2 ++
 xen/arch/x86/pv/mm.c                |  6 ++++++
 xen/include/asm-x86/domain.h        |  2 ++
 7 files changed, 48 insertions(+), 6 deletions(-)

diff --git a/xen/arch/x86/Kconfig b/xen/arch/x86/Kconfig
index 73ab8f8..6c89db1 100644
--- a/xen/arch/x86/Kconfig
+++ b/xen/arch/x86/Kconfig
@@ -164,3 +164,26 @@ endmenu
 source "common/Kconfig"
 
 source "drivers/Kconfig"
+
+menu "Deprecated Functionality"
+
+config LEGACY_PV_LDT_PAGING
+       def_bool n
+       prompt "PV LDT Paging-out support"
+       ---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@xxxxxxxxxxxxxxxxxxxx urgently.  Baring
+         something unexpected, the code and this option will be deleted 2
+         releases after Xen 4.12.
+
+endmenu
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index 4cdcd5d..64b40c7 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -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);
             }
         }
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 7da9a04..5aae19c 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -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_LEGACY_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_LEGACY_PV_LDT_PAGING */
         put_page(page);
     }
 }
diff --git a/xen/arch/x86/pv/descriptor-tables.c 
b/xen/arch/x86/pv/descriptor-tables.c
index 9b84cbe..93fd6e2 100644
--- a/xen/arch/x86/pv/descriptor-tables.c
+++ b/xen/arch/x86/pv/descriptor-tables.c
@@ -37,10 +37,14 @@ bool pv_destroy_ldt(struct vcpu *v)
 
     ASSERT(!in_irq());
 
+#ifdef CONFIG_LEGACY_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_LEGACY_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;
 
diff --git a/xen/arch/x86/pv/domain.c b/xen/arch/x86/pv/domain.c
index ce50dac..617fc74 100644
--- a/xen/arch/x86/pv/domain.c
+++ b/xen/arch/x86/pv/domain.c
@@ -171,7 +171,9 @@ int pv_vcpu_initialise(struct vcpu *v)
 
     ASSERT(!is_idle_domain(d));
 
+#ifdef CONFIG_LEGACY_PV_LDT_PAGING
     spin_lock_init(&v->arch.pv.shadow_ldt_lock);
+#endif
 
     rc = pv_create_gdt_ldt_l1tab(v);
     if ( rc )
diff --git a/xen/arch/x86/pv/mm.c b/xen/arch/x86/pv/mm.c
index e9156ea..0b0c653 100644
--- a/xen/arch/x86/pv/mm.c
+++ b/xen/arch/x86/pv/mm.c
@@ -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_LEGACY_PV_LDT_PAGING
     spin_lock(&curr->arch.pv.shadow_ldt_lock);
+#endif
+
     l1e_write(pl1e, gl1e);
+
+#ifdef CONFIG_LEGACY_PV_LDT_PAGING
     curr->arch.pv.shadow_ldt_mapcnt++;
     spin_unlock(&curr->arch.pv.shadow_ldt_lock);
+#endif
 
     return true;
 }
diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h
index 8eaed36..0da4c79 100644
--- a/xen/include/asm-x86/domain.h
+++ b/xen/include/asm-x86/domain.h
@@ -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_LEGACY_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];
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.