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

[Xen-changelog] Fix the support for PAE pgdirs above 4GB that was introduced in



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID d5f98d23427a0d256b896fc63ccfd2c1f79e55ba
# Parent  6d476981e3a5da8198f726dfb34904d33dea4f40
Fix the support for PAE pgdirs above 4GB that was introduced in
changeset 10173:954f4dea9da6336aaa35d0706aed55fde7909644.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/domain.c        |    2 
 xen/arch/x86/mm.c            |  158 +++++++++++++++++++++++++------------------
 xen/include/asm-x86/domain.h |   29 +++++--
 xen/include/asm-x86/fixmap.h |   10 +-
 4 files changed, 122 insertions(+), 77 deletions(-)

diff -r 6d476981e3a5 -r d5f98d23427a xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Sun May 28 15:49:17 2006 +0100
+++ b/xen/arch/x86/domain.c     Tue May 30 11:44:23 2006 +0100
@@ -146,6 +146,8 @@ struct vcpu *alloc_vcpu_struct(struct do
     v->arch.guest_vl4table = __linear_l4_table;
 #endif
 
+    pae_l3_cache_init(&v->arch.pae_l3_cache);
+
     return v;
 }
 
diff -r 6d476981e3a5 -r d5f98d23427a xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Sun May 28 15:49:17 2006 +0100
+++ b/xen/arch/x86/mm.c Tue May 30 11:44:23 2006 +0100
@@ -260,38 +260,78 @@ void share_xen_page_with_privileged_gues
     share_xen_page_with_guest(page, dom_xen, readonly);
 }
 
+#if defined(CONFIG_X86_PAE)
+
+#ifdef NDEBUG
+/* Only PDPTs above 4GB boundary need to be shadowed in low memory. */
+#define l3tab_needs_shadow(mfn) (mfn >= 0x100000)
+#else
+/* In debug builds we aggressively shadow PDPTs to exercise code paths. */
+#define l3tab_needs_shadow(mfn) ((mfn << PAGE_SHIFT) != __pa(idle_pg_table))
+#endif
+
+static l1_pgentry_t *fix_pae_highmem_pl1e;
+
+/* Cache the address of PAE high-memory fixmap page tables. */
+static int __init cache_pae_fixmap_address(void)
+{
+    unsigned long fixmap_base = fix_to_virt(FIX_PAE_HIGHMEM_0);
+    l2_pgentry_t *pl2e = virt_to_xen_l2e(fixmap_base);
+    fix_pae_highmem_pl1e = l2e_to_l1e(*pl2e) + l1_table_offset(fixmap_base);
+    return 0;
+}
+__initcall(cache_pae_fixmap_address);
+
 static void __write_ptbase(unsigned long mfn)
 {
-#ifdef CONFIG_X86_PAE
-    if ( mfn >= 0x100000 )
-    {
-        l3_pgentry_t *highmem_l3tab, *lowmem_l3tab;
-        struct vcpu *v = current;
-        unsigned long flags;
-
-        /* Protects against re-entry and against __pae_flush_pgd(). */
-        local_irq_save(flags);
-
-        /* Pick an unused low-memory L3 cache slot. */
-        v->arch.lowmem_l3tab_inuse ^= 1;
-        lowmem_l3tab = v->arch.lowmem_l3tab[v->arch.lowmem_l3tab_inuse];
-        v->arch.lowmem_l3tab_high_mfn[v->arch.lowmem_l3tab_inuse] = mfn;
-
-        /* Map the guest L3 table and copy to the chosen low-memory cache. */
-        highmem_l3tab = map_domain_page(mfn);
-        memcpy(lowmem_l3tab, highmem_l3tab, sizeof(v->arch.lowmem_l3tab));
-        unmap_domain_page(highmem_l3tab);
-
-        /* Install the low-memory L3 table in CR3. */
-        write_cr3(__pa(lowmem_l3tab));
-
-        local_irq_restore(flags);
+    l3_pgentry_t *highmem_l3tab, *lowmem_l3tab;
+    struct pae_l3_cache *cache = &current->arch.pae_l3_cache;
+    unsigned int cpu = smp_processor_id();
+
+    /* Fast path 1: does this mfn need a shadow at all? */
+    if ( !l3tab_needs_shadow(mfn) )
+    {
+        write_cr3(mfn << PAGE_SHIFT);
         return;
     }
-#endif
-
+
+    /* Caching logic is not interrupt safe. */
+    ASSERT(!in_irq());
+
+    /* Fast path 2: is this mfn already cached? */
+    if ( cache->high_mfn == mfn )
+    {
+        write_cr3(__pa(cache->table[cache->inuse_idx]));
+        return;
+    }
+
+    /* Protects against pae_flush_pgd(). */
+    spin_lock(&cache->lock);
+
+    cache->inuse_idx ^= 1;
+    cache->high_mfn   = mfn;
+
+    /* Map the guest L3 table and copy to the chosen low-memory cache. */
+    *(fix_pae_highmem_pl1e - cpu) = l1e_from_pfn(mfn, __PAGE_HYPERVISOR);
+    highmem_l3tab = (l3_pgentry_t *)fix_to_virt(FIX_PAE_HIGHMEM_0 + cpu);
+    lowmem_l3tab  = cache->table[cache->inuse_idx];
+    memcpy(lowmem_l3tab, highmem_l3tab, sizeof(cache->table[0]));
+    *(fix_pae_highmem_pl1e - cpu) = l1e_empty();
+
+    /* Install the low-memory L3 table in CR3. */
+    write_cr3(__pa(lowmem_l3tab));
+
+    spin_unlock(&cache->lock);
+}
+
+#else /* !CONFIG_X86_PAE */
+
+static void __write_ptbase(unsigned long mfn)
+{
     write_cr3(mfn << PAGE_SHIFT);
 }
+
+#endif /* !CONFIG_X86_PAE */
 
 void write_ptbase(struct vcpu *v)
 {
@@ -804,48 +844,39 @@ static int create_pae_xen_mappings(l3_pg
     return 1;
 }
 
-struct pae_flush_pgd {
-    unsigned long l3tab_mfn;
-    unsigned int  l3tab_idx;
-    l3_pgentry_t  nl3e;
-};
-
-static void __pae_flush_pgd(void *data)
-{
-    struct pae_flush_pgd *args = data;
-    struct vcpu *v = this_cpu(curr_vcpu);
-    int i = v->arch.lowmem_l3tab_inuse;
-    intpte_t _ol3e, _nl3e, _pl3e;
-    l3_pgentry_t *l3tab_ptr;
-
-    ASSERT(!local_irq_is_enabled());
-
-    if ( v->arch.lowmem_l3tab_high_mfn[i] != args->l3tab_mfn )
-        return;
-
-    l3tab_ptr = &v->arch.lowmem_l3tab[i][args->l3tab_idx];
-
-    _ol3e = l3e_get_intpte(*l3tab_ptr);
-    _nl3e = l3e_get_intpte(args->nl3e);
-    _pl3e = cmpxchg((intpte_t *)l3tab_ptr, _ol3e, _nl3e);
-    BUG_ON(_pl3e != _ol3e);
-}
-
 /* Flush a pgdir update into low-memory caches. */
 static void pae_flush_pgd(
     unsigned long mfn, unsigned int idx, l3_pgentry_t nl3e)
 {
     struct domain *d = page_get_owner(mfn_to_page(mfn));
-    struct pae_flush_pgd args = {
-        .l3tab_mfn = mfn,
-        .l3tab_idx = idx,
-        .nl3e      = nl3e };
+    struct vcpu   *v;
+    intpte_t       _ol3e, _nl3e, _pl3e;
+    l3_pgentry_t  *l3tab_ptr;
+    struct pae_l3_cache *cache;
 
     /* If below 4GB then the pgdir is not shadowed in low memory. */
-    if ( mfn < 0x100000 )
+    if ( !l3tab_needs_shadow(mfn) )
         return;
 
-    on_selected_cpus(d->domain_dirty_cpumask, __pae_flush_pgd, &args, 1, 1);
+    for_each_vcpu ( d, v )
+    {
+        cache = &v->arch.pae_l3_cache;
+
+        spin_lock(&cache->lock);
+
+        if ( cache->high_mfn == mfn )
+        {
+            l3tab_ptr = &cache->table[cache->inuse_idx][idx];
+            _ol3e = l3e_get_intpte(*l3tab_ptr);
+            _nl3e = l3e_get_intpte(nl3e);
+            _pl3e = cmpxchg((intpte_t *)l3tab_ptr, _ol3e, _nl3e);
+            BUG_ON(_pl3e != _ol3e);
+        }
+
+        spin_unlock(&cache->lock);
+    }
+
+    flush_tlb_mask(d->domain_dirty_cpumask);
 }
 
 static inline int l1_backptr(
@@ -3708,11 +3739,10 @@ int map_pages_to_xen(
 }
 
 void __set_fixmap(
-    enum fixed_addresses idx, unsigned long p, unsigned long flags)
-{
-    if ( unlikely(idx >= __end_of_fixed_addresses) )
-        BUG();
-    map_pages_to_xen(fix_to_virt(idx), p >> PAGE_SHIFT, 1, flags);
+    enum fixed_addresses idx, unsigned long mfn, unsigned long flags)
+{
+    BUG_ON(idx >= __end_of_fixed_addresses);
+    map_pages_to_xen(fix_to_virt(idx), mfn, 1, flags);
 }
 
 #ifdef MEMORY_GUARD
diff -r 6d476981e3a5 -r d5f98d23427a xen/include/asm-x86/domain.h
--- a/xen/include/asm-x86/domain.h      Sun May 28 15:49:17 2006 +0100
+++ b/xen/include/asm-x86/domain.h      Tue May 30 11:44:23 2006 +0100
@@ -114,23 +114,32 @@ struct arch_domain
     unsigned long first_reserved_pfn;
 } __cacheline_aligned;
 
-struct arch_vcpu
-{
-    /* Needs 16-byte aligment for FXSAVE/FXRSTOR. */
-    struct vcpu_guest_context guest_context
-    __attribute__((__aligned__(16)));
-
 #ifdef CONFIG_X86_PAE
+struct pae_l3_cache {
     /*
      * Two low-memory (<4GB) PAE L3 tables, used as fallback when the guest
      * supplies a >=4GB PAE L3 table. We need two because we cannot set up
      * an L3 table while we are currently running on it (without using
      * expensive atomic 64-bit operations).
      */
-    l3_pgentry_t  lowmem_l3tab[2][4] __attribute__((__aligned__(32)));
-    unsigned long lowmem_l3tab_high_mfn[2]; /* The >=4GB MFN being shadowed. */
-    unsigned int  lowmem_l3tab_inuse;       /* Which lowmem_l3tab is in use? */
-#endif
+    l3_pgentry_t  table[2][4] __attribute__((__aligned__(32)));
+    unsigned long high_mfn;  /* The >=4GB MFN being shadowed. */
+    unsigned int  inuse_idx; /* Which of the two cache slots is in use? */
+    spinlock_t    lock;
+};
+#define pae_l3_cache_init(c) spin_lock_init(&(c)->lock)
+#else /* !CONFIG_X86_PAE */
+struct pae_l3_cache { };
+#define pae_l3_cache_init(c) ((void)0)
+#endif
+
+struct arch_vcpu
+{
+    /* Needs 16-byte aligment for FXSAVE/FXRSTOR. */
+    struct vcpu_guest_context guest_context
+    __attribute__((__aligned__(16)));
+
+    struct pae_l3_cache pae_l3_cache;
 
     unsigned long      flags; /* TF_ */
 
diff -r 6d476981e3a5 -r d5f98d23427a xen/include/asm-x86/fixmap.h
--- a/xen/include/asm-x86/fixmap.h      Sun May 28 15:49:17 2006 +0100
+++ b/xen/include/asm-x86/fixmap.h      Tue May 30 11:44:23 2006 +0100
@@ -25,6 +25,10 @@
  * from the end of virtual memory backwards.
  */
 enum fixed_addresses {
+#ifdef CONFIG_X86_PAE
+    FIX_PAE_HIGHMEM_0,
+    FIX_PAE_HIGHMEM_END = FIX_PAE_HIGHMEM_0 + NR_CPUS-1,
+#endif
     FIX_APIC_BASE,
     FIX_IO_APIC_BASE_0,
     FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS-1,
@@ -40,13 +44,13 @@ enum fixed_addresses {
 #define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
 
 extern void __set_fixmap(
-    enum fixed_addresses idx, unsigned long p, unsigned long flags);
+    enum fixed_addresses idx, unsigned long mfn, unsigned long flags);
 
 #define set_fixmap(idx, phys) \
-    __set_fixmap(idx, phys, PAGE_HYPERVISOR)
+    __set_fixmap(idx, (phys)>>PAGE_SHIFT, PAGE_HYPERVISOR)
 
 #define set_fixmap_nocache(idx, phys) \
-    __set_fixmap(idx, phys, PAGE_HYPERVISOR_NOCACHE)
+    __set_fixmap(idx, (phys)>>PAGE_SHIFT, PAGE_HYPERVISOR_NOCACHE)
 
 #define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
 #define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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