WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

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

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] Fix the support for PAE pgdirs above 4GB that was introduced in
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Tue, 30 May 2006 12:06:10 +0000
Delivery-date: Tue, 30 May 2006 05:07:45 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] Fix the support for PAE pgdirs above 4GB that was introduced in, Xen patchbot-unstable <=