x86: unify PAE/non-PAE pgd_ctor
authorJeremy Fitzhardinge <jeremy@goop.org>
Mon, 4 Feb 2008 15:48:02 +0000 (16:48 +0100)
committerIngo Molnar <mingo@elte.hu>
Mon, 4 Feb 2008 15:48:02 +0000 (16:48 +0100)
The constructors for PAE and non-PAE pgd_ctors are more or less
identical, and can be made into the same function.

Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com>
Cc: William Irwin <wli@holomorphy.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
arch/x86/mm/pgtable_32.c

index cb3aa47..f34e33d 100644 (file)
@@ -219,50 +219,39 @@ static inline void pgd_list_del(pgd_t *pgd)
        list_del(&page->lru);
 }
 
+#define UNSHARED_PTRS_PER_PGD                          \
+       (SHARED_KERNEL_PMD ? USER_PTRS_PER_PGD : PTRS_PER_PGD)
 
-
-#if (PTRS_PER_PMD == 1)
-/* Non-PAE pgd constructor */
-static void pgd_ctor(void *pgd)
+static void pgd_ctor(void *p)
 {
+       pgd_t *pgd = p;
        unsigned long flags;
 
-       /* !PAE, no pagetable sharing */
+       /* Clear usermode parts of PGD */
        memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
 
        spin_lock_irqsave(&pgd_lock, flags);
 
-       /* must happen under lock */
-       clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
-                       swapper_pg_dir + USER_PTRS_PER_PGD,
-                       KERNEL_PGD_PTRS);
-       paravirt_alloc_pd_clone(__pa(pgd) >> PAGE_SHIFT,
-                               __pa(swapper_pg_dir) >> PAGE_SHIFT,
-                               USER_PTRS_PER_PGD,
-                               KERNEL_PGD_PTRS);
-       pgd_list_add(pgd);
-       spin_unlock_irqrestore(&pgd_lock, flags);
-}
-#else  /* PTRS_PER_PMD > 1 */
-/* PAE pgd constructor */
-static void pgd_ctor(void *pgd)
-{
-       /* PAE, kernel PMD may be shared */
-
-       if (SHARED_KERNEL_PMD) {
-               clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
+       /* If the pgd points to a shared pagetable level (either the
+          ptes in non-PAE, or shared PMD in PAE), then just copy the
+          references from swapper_pg_dir. */
+       if (PAGETABLE_LEVELS == 2 ||
+           (PAGETABLE_LEVELS == 3 && SHARED_KERNEL_PMD)) {
+               clone_pgd_range(pgd + USER_PTRS_PER_PGD,
                                swapper_pg_dir + USER_PTRS_PER_PGD,
                                KERNEL_PGD_PTRS);
-       } else {
-               unsigned long flags;
+               paravirt_alloc_pd_clone(__pa(pgd) >> PAGE_SHIFT,
+                                       __pa(swapper_pg_dir) >> PAGE_SHIFT,
+                                       USER_PTRS_PER_PGD,
+                                       KERNEL_PGD_PTRS);
+       }
 
-               memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
-               spin_lock_irqsave(&pgd_lock, flags);
+       /* list required to sync kernel mapping updates */
+       if (!SHARED_KERNEL_PMD)
                pgd_list_add(pgd);
-               spin_unlock_irqrestore(&pgd_lock, flags);
-       }
+
+       spin_unlock_irqrestore(&pgd_lock, flags);
 }
-#endif /* PTRS_PER_PMD */
 
 static void pgd_dtor(void *pgd)
 {
@@ -276,9 +265,6 @@ static void pgd_dtor(void *pgd)
        spin_unlock_irqrestore(&pgd_lock, flags);
 }
 
-#define UNSHARED_PTRS_PER_PGD                          \
-       (SHARED_KERNEL_PMD ? USER_PTRS_PER_PGD : PTRS_PER_PGD)
-
 #ifdef CONFIG_X86_PAE
 /*
  * Mop up any pmd pages which may still be attached to the pgd.