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

[Xen-changelog] Big reworking of SHARED_KERNEL_PMD logic. Includes several



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID b0338759544e116337f25d5cdebc59c38a6d40c5
# Parent  78b5e590be34ee3454d970321d7c2f3199a0de41
Big reworking of SHARED_KERNEL_PMD logic. Includes several
bug fixes for PAE, and reverts my previous changeset that
broke non-pae.

Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>

diff -r 78b5e590be34 -r b0338759544e 
linux-2.6-xen-sparse/arch/xen/i386/mm/init.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/mm/init.c      Thu Nov 24 19:57:01 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/init.c      Thu Nov 24 22:21:48 2005
@@ -708,7 +708,7 @@
                        panic("pgtable_cache_init(): cannot create pmd cache");
        }
        pgd_cache = kmem_cache_create("pgd",
-#if 0 /* How the heck _this_ works in native linux ??? */
+#ifndef CONFIG_XEN
                                PTRS_PER_PGD*sizeof(pgd_t),
                                PTRS_PER_PGD*sizeof(pgd_t),
 #else
@@ -717,7 +717,7 @@
 #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 78b5e590be34 -r b0338759544e 
linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c   Thu Nov 24 19:57:01 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c   Thu Nov 24 22:21:48 2005
@@ -28,8 +28,6 @@
 #include <asm/hypervisor.h>
 
 static void pgd_test_and_unpin(pgd_t *pgd);
-#define suspend_disable        preempt_disable
-#define suspend_enable preempt_enable
 
 void show_mem(void)
 {
@@ -279,26 +277,31 @@
 {
        unsigned long flags;
 
-#ifdef CONFIG_X86_PAE
-       /* Ensure pgd resides below 4GB. */
-       int rc = xen_create_contiguous_region((unsigned long)pgd, 0, 32);
-       BUG_ON(rc);
+       if (PTRS_PER_PMD > 1) {
+#ifdef CONFIG_XEN
+               /* Ensure pgd resides below 4GB. */
+               int rc = xen_create_contiguous_region(
+                       (unsigned long)pgd, 0, 32);
+               BUG_ON(rc);
 #endif
-
-       if (HAVE_SHARED_KERNEL_PMD) {
+               if (HAVE_SHARED_KERNEL_PMD)
+                       memcpy((pgd_t *)pgd + USER_PTRS_PER_PGD,
+                              swapper_pg_dir, sizeof(pgd_t));
+       } else {
+               if (!HAVE_SHARED_KERNEL_PMD)
+                       spin_lock_irqsave(&pgd_lock, flags);
                memcpy((pgd_t *)pgd + USER_PTRS_PER_PGD,
                       swapper_pg_dir + USER_PTRS_PER_PGD,
                       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
-               return;
-       }
-
-       memset(pgd, 0, PTRS_PER_PGD*sizeof(pgd_t));
-
-       spin_lock_irqsave(&pgd_lock, flags);
-       pgd_list_add(pgd);
-       spin_unlock_irqrestore(&pgd_lock, flags);
-}
-
+               memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
+               if (!HAVE_SHARED_KERNEL_PMD) {
+                       pgd_list_add(pgd);
+                       spin_unlock_irqrestore(&pgd_lock, flags);
+               }
+       }
+}
+
+/* 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 */
@@ -315,7 +318,7 @@
 
 pgd_t *pgd_alloc(struct mm_struct *mm)
 {
-       int i = 0;
+       int i;
        pgd_t *pgd = kmem_cache_alloc(pgd_cache, GFP_KERNEL);
 
        pgd_test_and_unpin(pgd);
@@ -323,34 +326,31 @@
        if (PTRS_PER_PMD == 1 || !pgd)
                return pgd;
 
+       for (i = 0; i < USER_PTRS_PER_PGD; ++i) {
+               pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
+               if (!pmd)
+                       goto out_oom;
+               set_pgd(&pgd[i], __pgd(1 + __pa(pmd)));
+       }
+
        if (!HAVE_SHARED_KERNEL_PMD) {
-               /* alloc and copy kernel pmd */
                unsigned long flags;
                pgd_t *copy_pgd = pgd_offset_k(PAGE_OFFSET);
                pud_t *copy_pud = pud_offset(copy_pgd, PAGE_OFFSET);
                pmd_t *copy_pmd = pmd_offset(copy_pud, PAGE_OFFSET);
                pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
-               if (0 == pmd)
+               ++i;
+               if (!pmd)
                        goto out_oom;
 
                spin_lock_irqsave(&pgd_lock, flags);
                memcpy(pmd, copy_pmd, PAGE_SIZE);
-               spin_unlock_irqrestore(&pgd_lock, flags);
                make_lowmem_page_readonly(pmd);
                set_pgd(&pgd[USER_PTRS_PER_PGD], __pgd(1 + __pa(pmd)));
-       }
-
-       /* alloc user pmds */
-       for (i = 0; i < USER_PTRS_PER_PGD; ++i) {
-               pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
-               if (!pmd)
-                       goto out_oom;
-               suspend_disable();
-               if (test_bit(PG_pinned, &virt_to_page(pgd)->flags))
-                       make_lowmem_page_readonly(pmd);
-               set_pgd(&pgd[i], __pgd(1 + __pa(pmd)));
-               suspend_enable();
-       }
+               pgd_list_add(pgd);
+               spin_unlock_irqrestore(&pgd_lock, flags);
+       }
+
        return pgd;
 
 out_oom:
@@ -364,28 +364,25 @@
 {
        int i;
 
-       suspend_disable();
        pgd_test_and_unpin(pgd);
 
        /* in the PAE case user pgd entries are overwritten before usage */
        if (PTRS_PER_PMD > 1) {
                for (i = 0; i < USER_PTRS_PER_PGD; ++i) {
                        pmd_t *pmd = (void *)__va(pgd_val(pgd[i])-1);
-                       set_pgd(&pgd[i], __pgd(0));
-                       make_lowmem_page_writable(pmd);
                        kmem_cache_free(pmd_cache, pmd);
                }
                if (!HAVE_SHARED_KERNEL_PMD) {
+                       unsigned long flags;
                        pmd_t *pmd = (void 
*)__va(pgd_val(pgd[USER_PTRS_PER_PGD])-1);
-                       set_pgd(&pgd[USER_PTRS_PER_PGD], __pgd(0));
+                       spin_lock_irqsave(&pgd_lock, flags);
+                       pgd_list_del(pgd);
+                       spin_unlock_irqrestore(&pgd_lock, flags);
                        make_lowmem_page_writable(pmd);
                        memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t));
                        kmem_cache_free(pmd_cache, pmd);
                }
        }
-
-       suspend_enable();
-
        /* in the non-PAE case, free_pgtables() clears user pgd entries */
        kmem_cache_free(pgd_cache, pgd);
 }
@@ -510,9 +507,6 @@
 
 static void __pgd_pin(pgd_t *pgd)
 {
-       /* PAE PGDs with no kernel PMD cannot be pinned. Bail right now. */
-       if ((PTRS_PER_PMD > 1) && pgd_none(pgd[USER_PTRS_PER_PGD]))
-               return;
        pgd_walk(pgd, PAGE_KERNEL_RO);
        xen_pgd_pin(__pa(pgd));
        set_bit(PG_pinned, &virt_to_page(pgd)->flags);
@@ -527,10 +521,8 @@
 
 static void pgd_test_and_unpin(pgd_t *pgd)
 {
-       suspend_disable();
        if (test_bit(PG_pinned, &virt_to_page(pgd)->flags))
                __pgd_unpin(pgd);
-       suspend_enable();
 }
 
 void mm_pin(struct mm_struct *mm)
diff -r 78b5e590be34 -r b0338759544e patches/linux-2.6.12/pmd-shared.patch
--- a/patches/linux-2.6.12/pmd-shared.patch     Thu Nov 24 19:57:01 2005
+++ b/patches/linux-2.6.12/pmd-shared.patch     Thu Nov 24 22:21:48 2005
@@ -1,15 +1,3 @@
-diff -urNpP linux-2.6.12/arch/i386/mm/init.c 
linux-2.6.12.new/arch/i386/mm/init.c
---- linux-2.6.12/arch/i386/mm/init.c   2005-06-17 20:48:29.000000000 +0100
-+++ linux-2.6.12.new/arch/i386/mm/init.c       2005-07-11 16:28:09.778165582 
+0100
-@@ -634,7 +634,7 @@ void __init pgtable_cache_init(void)
-                               PTRS_PER_PGD*sizeof(pgd_t),
-                               0,
-                               pgd_ctor,
--                              PTRS_PER_PMD == 1 ? pgd_dtor : NULL);
-+                              pgd_dtor);
-       if (!pgd_cache)
-               panic("pgtable_cache_init(): Cannot create pgd cache");
- }
 diff -urNpP linux-2.6.12/arch/i386/mm/pageattr.c 
linux-2.6.12.new/arch/i386/mm/pageattr.c
 --- linux-2.6.12/arch/i386/mm/pageattr.c       2005-06-17 20:48:29.000000000 
+0100
 +++ linux-2.6.12.new/arch/i386/mm/pageattr.c   2005-07-11 16:28:09.775165494 
+0100
@@ -23,31 +11,45 @@
  
        spin_lock_irqsave(&pgd_lock, flags);
 diff -urNpP linux-2.6.12/arch/i386/mm/pgtable.c 
linux-2.6.12.new/arch/i386/mm/pgtable.c
---- linux-2.6.12/arch/i386/mm/pgtable.c        2005-06-17 20:48:29.000000000 
+0100
-+++ linux-2.6.12.new/arch/i386/mm/pgtable.c    2005-07-11 16:32:01.478023726 
+0100
-@@ -199,14 +199,14 @@ void pgd_ctor(void *pgd, kmem_cache_t *c
+--- linux-2.6.12/arch/i386/mm/pgtable.c        2005-11-24 21:51:49.000000000 
+0000
++++ linux-2.6.12.new/arch/i386/mm/pgtable.c    2005-11-24 22:06:04.000000000 
+0000
+@@ -199,19 +199,22 @@ void pgd_ctor(void *pgd, kmem_cache_t *c
  {
        unsigned long flags;
  
 -      if (PTRS_PER_PMD == 1)
-+      if (!HAVE_SHARED_KERNEL_PMD)
-               spin_lock_irqsave(&pgd_lock, flags);
- 
-       memcpy((pgd_t *)pgd + USER_PTRS_PER_PGD,
-                       swapper_pg_dir + USER_PTRS_PER_PGD,
-                       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
- 
+-              spin_lock_irqsave(&pgd_lock, flags);
+-
+-      memcpy((pgd_t *)pgd + USER_PTRS_PER_PGD,
+-                      swapper_pg_dir + USER_PTRS_PER_PGD,
+-                      (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+-
 -      if (PTRS_PER_PMD > 1)
-+      if (HAVE_SHARED_KERNEL_PMD)
-               return;
- 
-       pgd_list_add(pgd);
-@@ -214,11 +214,13 @@ void pgd_ctor(void *pgd, kmem_cache_t *c
-       memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
+-              return;
+-
+-      pgd_list_add(pgd);
+-      spin_unlock_irqrestore(&pgd_lock, flags);
+-      memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
++      if (PTRS_PER_PMD > 1) {
++              if (HAVE_SHARED_KERNEL_PMD)
++                      memcpy((pgd_t *)pgd + USER_PTRS_PER_PGD,
++                             swapper_pg_dir, sizeof(pgd_t));
++      } else {
++              if (!HAVE_SHARED_KERNEL_PMD)
++                      spin_lock_irqsave(&pgd_lock, flags);
++              memcpy((pgd_t *)pgd + USER_PTRS_PER_PGD,
++                     swapper_pg_dir + USER_PTRS_PER_PGD,
++                     (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
++              memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
++              if (!HAVE_SHARED_KERNEL_PMD) {
++                      pgd_list_add(pgd);
++                      spin_unlock_irqrestore(&pgd_lock, flags);
++              }
++      }
  }
  
--/* never called when PTRS_PER_PMD > 1 */
- void pgd_dtor(void *pgd, kmem_cache_t *cache, unsigned long unused)
+ /* never called when PTRS_PER_PMD > 1 */
+@@ -219,6 +222,9 @@ void pgd_dtor(void *pgd, kmem_cache_t *c
  {
        unsigned long flags; /* can be called from interrupt context */
  
@@ -57,38 +59,32 @@
        spin_lock_irqsave(&pgd_lock, flags);
        pgd_list_del(pgd);
        spin_unlock_irqrestore(&pgd_lock, flags);
-@@ -226,12 +228,29 @@ void pgd_dtor(void *pgd, kmem_cache_t *c
- 
- pgd_t *pgd_alloc(struct mm_struct *mm)
- {
--      int i;
-+      int i = 0;
-       pgd_t *pgd = kmem_cache_alloc(pgd_cache, GFP_KERNEL);
- 
-       if (PTRS_PER_PMD == 1 || !pgd)
-               return pgd;
- 
+@@ -238,6 +244,24 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
+                       goto out_oom;
+               set_pgd(&pgd[i], __pgd(1 + __pa(pmd)));
+       }
++
 +      if (!HAVE_SHARED_KERNEL_PMD) {
-+              /* alloc and copy kernel pmd */
 +              unsigned long flags;
 +              pgd_t *copy_pgd = pgd_offset_k(PAGE_OFFSET);
 +              pud_t *copy_pud = pud_offset(copy_pgd, PAGE_OFFSET);
 +              pmd_t *copy_pmd = pmd_offset(copy_pud, PAGE_OFFSET);
 +              pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
-+              if (0 == pmd)
++                ++i;
++              if (!pmd)
 +                      goto out_oom;
 +
 +              spin_lock_irqsave(&pgd_lock, flags);
 +              memcpy(pmd, copy_pmd, PAGE_SIZE);
++              set_pgd(&pgd[USER_PTRS_PER_PGD], __pgd(1 + __pa(pmd)));
++              pgd_list_add(pgd);
 +              spin_unlock_irqrestore(&pgd_lock, flags);
-+              set_pgd(&pgd[USER_PTRS_PER_PGD], __pgd(1 + __pa(pmd)));
 +      }
 +
-+      /* alloc user pmds */
-       for (i = 0; i < USER_PTRS_PER_PGD; ++i) {
-               pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
-               if (!pmd)
-@@ -252,9 +271,16 @@ void pgd_free(pgd_t *pgd)
+       return pgd;
+ 
+ out_oom:
+@@ -252,9 +276,21 @@ void pgd_free(pgd_t *pgd)
        int i;
  
        /* in the PAE case user pgd entries are overwritten before usage */
@@ -101,7 +97,12 @@
 +                      kmem_cache_free(pmd_cache, pmd);
 +              }
 +              if (!HAVE_SHARED_KERNEL_PMD) {
++                      unsigned long flags;
 +                      pmd_t *pmd = (void 
*)__va(pgd_val(pgd[USER_PTRS_PER_PGD])-1);
++                      spin_lock_irqsave(&pgd_lock, flags);
++                      pgd_list_del(pgd);
++                      spin_unlock_irqrestore(&pgd_lock, flags);
++                      memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t));
 +                      kmem_cache_free(pmd_cache, pmd);
 +              }
 +      }

_______________________________________________
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®.