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] [xen-unstable] [LINUX][PAE] Improve allocation strategy

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [LINUX][PAE] Improve allocation strategy when PAE pgdirs must be below 4GB.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 14 Jun 2006 15:25:33 +0000
Delivery-date: Wed, 14 Jun 2006 08:28:33 -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 8070050cc30f3d969835d7b1d6eda57959d56842
# Parent  5552bc2c3716e9e0f57dbba80f61332b895a0f2a
[LINUX][PAE] Improve allocation strategy when PAE pgdirs must be below 4GB.
Moving the re-allocation to low memory into pgd_alloc() has several
advantages:
 1. Avoids race with save/restore where pgdir may end up above 4GB after
    save/restore.
 2. If pgdir cannot be re-allocated we can return failure to the caller
    rather than BUG().
 3. Slightly reduces diff against native Linux code.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 linux-2.6-xen-sparse/arch/i386/mm/init-xen.c    |    2 
 linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c |   57 ++++++++++++++++--------
 2 files changed, 40 insertions(+), 19 deletions(-)

diff -r 5552bc2c3716 -r 8070050cc30f 
linux-2.6-xen-sparse/arch/i386/mm/init-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/mm/init-xen.c      Wed Jun 14 11:19:53 
2006 +0100
+++ b/linux-2.6-xen-sparse/arch/i386/mm/init-xen.c      Wed Jun 14 12:36:06 
2006 +0100
@@ -763,7 +763,7 @@ void __init pgtable_cache_init(void)
 #endif
                                0,
                                pgd_ctor,
-                               pgd_dtor);
+                               PTRS_PER_PMD == 1 ? pgd_dtor : NULL);
        if (!pgd_cache)
                panic("pgtable_cache_init(): Cannot create pgd cache");
 }
diff -r 5552bc2c3716 -r 8070050cc30f 
linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c   Wed Jun 14 11:19:53 
2006 +0100
+++ b/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c   Wed Jun 14 12:36:06 
2006 +0100
@@ -300,11 +300,6 @@ void pgd_ctor(void *pgd, kmem_cache_t *c
        unsigned long flags;
 
        if (PTRS_PER_PMD > 1) {
-               if (!xen_feature(XENFEAT_pae_pgdir_above_4gb)) {
-                       int rc = xen_create_contiguous_region(
-                               (unsigned long)pgd, 0, 32);
-                       BUG_ON(rc);
-               }
                if (HAVE_SHARED_KERNEL_PMD)
                        clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
                                        swapper_pg_dir + USER_PTRS_PER_PGD,
@@ -320,26 +315,22 @@ void pgd_ctor(void *pgd, kmem_cache_t *c
        }
 }
 
+/* never called when PTRS_PER_PMD > 1 */
 void pgd_dtor(void *pgd, kmem_cache_t *cache, unsigned long unused)
 {
        unsigned long flags; /* can be called from interrupt context */
 
-       if (PTRS_PER_PMD > 1) {
-               if (!xen_feature(XENFEAT_pae_pgdir_above_4gb))
-                       xen_destroy_contiguous_region((unsigned long)pgd, 0);
-       } else {
-               spin_lock_irqsave(&pgd_lock, flags);
-               pgd_list_del(pgd);
-               spin_unlock_irqrestore(&pgd_lock, flags);
-
-               pgd_test_and_unpin(pgd);
-       }
+       spin_lock_irqsave(&pgd_lock, flags);
+       pgd_list_del(pgd);
+       spin_unlock_irqrestore(&pgd_lock, flags);
+
+       pgd_test_and_unpin(pgd);
 }
 
 pgd_t *pgd_alloc(struct mm_struct *mm)
 {
        int i;
-       pgd_t *pgd = kmem_cache_alloc(pgd_cache, GFP_KERNEL);
+       pgd_t *pgd_tmp = NULL, *pgd = kmem_cache_alloc(pgd_cache, GFP_KERNEL);
 
        pgd_test_and_unpin(pgd);
 
@@ -363,7 +354,26 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
                        set_pgd(&pgd[i], __pgd(1 + __pa(pmd)));
                }
 
+               /* create_contig_region() loses page data. Make a temp copy. */
+               if (!xen_feature(XENFEAT_pae_pgdir_above_4gb)) {
+                       pgd_tmp = kmem_cache_alloc(pgd_cache, GFP_KERNEL);
+                       if (!pgd_tmp)
+                               goto out_oom;
+                       memcpy(pgd_tmp, pgd, PAGE_SIZE);
+               }
+
                spin_lock_irqsave(&pgd_lock, flags);
+
+               /* Protect against save/restore: move below 4GB with lock. */
+               if (!xen_feature(XENFEAT_pae_pgdir_above_4gb)) {
+                       int rc = xen_create_contiguous_region(
+                               (unsigned long)pgd, 0, 32);
+                       memcpy(pgd, pgd_tmp, PAGE_SIZE);
+                       kmem_cache_free(pgd_cache, pgd_tmp);
+                       if (rc)
+                               goto out_oom;
+               }
+
                for (i = USER_PTRS_PER_PGD; i < PTRS_PER_PGD; i++) {
                        unsigned long v = (unsigned long)i << PGDIR_SHIFT;
                        pgd_t *kpgd = pgd_offset_k(v);
@@ -374,7 +384,9 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
                        make_lowmem_page_readonly(
                                pmd, XENFEAT_writable_page_tables);
                }
+
                pgd_list_add(pgd);
+
                spin_unlock_irqrestore(&pgd_lock, flags);
        }
 
@@ -399,11 +411,15 @@ void pgd_free(pgd_t *pgd)
                        pmd_t *pmd = (void *)__va(pgd_val(pgd[i])-1);
                        kmem_cache_free(pmd_cache, pmd);
                }
+
                if (!HAVE_SHARED_KERNEL_PMD) {
                        unsigned long flags;
                        spin_lock_irqsave(&pgd_lock, flags);
                        pgd_list_del(pgd);
                        spin_unlock_irqrestore(&pgd_lock, flags);
+
+                       pgd_test_and_unpin(pgd);
+
                        for (i = USER_PTRS_PER_PGD; i < PTRS_PER_PGD; i++) {
                                pmd_t *pmd = (void *)__va(pgd_val(pgd[i])-1);
                                make_lowmem_page_writable(
@@ -411,8 +427,13 @@ void pgd_free(pgd_t *pgd)
                                memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t));
                                kmem_cache_free(pmd_cache, pmd);
                        }
-               }
-       }
+
+                       if (!xen_feature(XENFEAT_pae_pgdir_above_4gb))
+                               xen_destroy_contiguous_region(
+                                       (unsigned long)pgd, 0);
+               }
+       }
+
        /* in the non-PAE case, free_pgtables() clears user pgd entries */
        kmem_cache_free(pgd_cache, pgd);
 }

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [LINUX][PAE] Improve allocation strategy when PAE pgdirs must be below 4GB., Xen patchbot-unstable <=