[patch 08/21] Xen-paravirt: Allow paravirt backend to choose kernel PMD sharing

2007-02-15 Thread Jeremy Fitzhardinge
Xen does not allow guests to have the kernel pmd shared between page
tables, so parameterize pgtable.c to allow both modes of operation.

Signed-off-by: Jeremy Fitzhardinge <[EMAIL PROTECTED]>
--
 arch/i386/kernel/paravirt.c|1 
 arch/i386/mm/fault.c   |6 +--
 arch/i386/mm/pageattr.c|2 -
 arch/i386/mm/pgtable.c |   61 +++
 include/asm-i386/page.h|7 ++-
 include/asm-i386/paravirt.h|1 
 include/asm-i386/pgtable-2level-defs.h |2 +
 include/asm-i386/pgtable-2level.h  |2 -
 include/asm-i386/pgtable-3level-defs.h |6 +++
 include/asm-i386/pgtable-3level.h  |   16 ++--
 include/asm-i386/pgtable.h |7 +++
 11 files changed, 68 insertions(+), 43 deletions(-)

===
--- a/arch/i386/kernel/paravirt.c
+++ b/arch/i386/kernel/paravirt.c
@@ -572,6 +572,7 @@ struct paravirt_ops paravirt_ops = {
.name = "bare hardware",
.paravirt_enabled = 0,
.kernel_rpl = 0,
+   .shared_kernel_pmd = 1, /* Only used when CONFIG_X86_PAE is set */
 
.patch = native_patch,
.banner = default_banner,
===
--- a/arch/i386/mm/fault.c
+++ b/arch/i386/mm/fault.c
@@ -616,8 +616,7 @@ do_sigbus:
force_sig_info_fault(SIGBUS, BUS_ADRERR, address, tsk);
 }
 
-#ifndef CONFIG_X86_PAE
-void vmalloc_sync_all(void)
+void _vmalloc_sync_all(void)
 {
/*
 * Note that races in the updates of insync and start aren't
@@ -628,6 +627,8 @@ void vmalloc_sync_all(void)
static DECLARE_BITMAP(insync, PTRS_PER_PGD);
static unsigned long start = TASK_SIZE;
unsigned long address;
+
+   BUG_ON(SHARED_KERNEL_PMD);
 
BUILD_BUG_ON(TASK_SIZE & ~PGDIR_MASK);
for (address = start; address >= TASK_SIZE; address += PGDIR_SIZE) {
@@ -651,4 +652,3 @@ void vmalloc_sync_all(void)
start = address + PGDIR_SIZE;
}
 }
-#endif
===
--- a/arch/i386/mm/pageattr.c
+++ b/arch/i386/mm/pageattr.c
@@ -91,7 +91,7 @@ static void set_pmd_pte(pte_t *kpte, uns
unsigned long flags;
 
set_pte_atomic(kpte, pte);  /* change init_mm */
-   if (PTRS_PER_PMD > 1)
+   if (SHARED_KERNEL_PMD)
return;
 
spin_lock_irqsave(_lock, flags);
===
--- a/arch/i386/mm/pgtable.c
+++ b/arch/i386/mm/pgtable.c
@@ -241,31 +241,42 @@ static void pgd_ctor(pgd_t *pgd)
unsigned long flags;
 
if (PTRS_PER_PMD == 1) {
+   /* !PAE, no pagetable sharing */
memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
+
+   clone_pgd_range(pgd + USER_PTRS_PER_PGD,
+   swapper_pg_dir + USER_PTRS_PER_PGD,
+   KERNEL_PGD_PTRS);
+
spin_lock_irqsave(_lock, flags);
-   }
-
-   clone_pgd_range(pgd + USER_PTRS_PER_PGD,
-   swapper_pg_dir + USER_PTRS_PER_PGD,
-   KERNEL_PGD_PTRS);
-
-   if (PTRS_PER_PMD > 1)
-   return;
-
-   /* must happen under lock */
-   paravirt_alloc_pd_clone(__pa(pgd) >> PAGE_SHIFT,
-   __pa(swapper_pg_dir) >> PAGE_SHIFT,
-   USER_PTRS_PER_PGD, PTRS_PER_PGD - USER_PTRS_PER_PGD);
-
-   pgd_list_add(pgd);
-   spin_unlock_irqrestore(_lock, flags);
+
+   /* must happen under lock */
+   paravirt_alloc_pd_clone(__pa(pgd) >> PAGE_SHIFT,
+   __pa(swapper_pg_dir) >> PAGE_SHIFT,
+   USER_PTRS_PER_PGD,
+   PTRS_PER_PGD - USER_PTRS_PER_PGD);
+
+   pgd_list_add(pgd);
+   spin_unlock_irqrestore(_lock, flags);
+   } else {
+   /* PAE, PMD may be shared */
+   if (SHARED_KERNEL_PMD) {
+   clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
+   swapper_pg_dir + USER_PTRS_PER_PGD,
+   KERNEL_PGD_PTRS);
+   } else {
+   spin_lock_irqsave(_lock, flags);
+   pgd_list_add(pgd);
+   spin_unlock_irqrestore(_lock, flags);
+   }
+   }
 }
 
 static void pgd_dtor(pgd_t *pgd)
 {
unsigned long flags; /* can be called from interrupt context */
 
-   if (PTRS_PER_PMD == 1)
+   if (SHARED_KERNEL_PMD)
return;
 
paravirt_release_pd(__pa(pgd) >> PAGE_SHIFT);
@@ -279,19 +290,25 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
int i;
pgd_t *pgd = kmem_cache_alloc(pgd_cache, GFP_KERNEL);
 
-   if (pgd)
+   if 

[patch 08/21] Xen-paravirt: Allow paravirt backend to choose kernel PMD sharing

2007-02-15 Thread Jeremy Fitzhardinge
Xen does not allow guests to have the kernel pmd shared between page
tables, so parameterize pgtable.c to allow both modes of operation.

Signed-off-by: Jeremy Fitzhardinge [EMAIL PROTECTED]
--
 arch/i386/kernel/paravirt.c|1 
 arch/i386/mm/fault.c   |6 +--
 arch/i386/mm/pageattr.c|2 -
 arch/i386/mm/pgtable.c |   61 +++
 include/asm-i386/page.h|7 ++-
 include/asm-i386/paravirt.h|1 
 include/asm-i386/pgtable-2level-defs.h |2 +
 include/asm-i386/pgtable-2level.h  |2 -
 include/asm-i386/pgtable-3level-defs.h |6 +++
 include/asm-i386/pgtable-3level.h  |   16 ++--
 include/asm-i386/pgtable.h |7 +++
 11 files changed, 68 insertions(+), 43 deletions(-)

===
--- a/arch/i386/kernel/paravirt.c
+++ b/arch/i386/kernel/paravirt.c
@@ -572,6 +572,7 @@ struct paravirt_ops paravirt_ops = {
.name = bare hardware,
.paravirt_enabled = 0,
.kernel_rpl = 0,
+   .shared_kernel_pmd = 1, /* Only used when CONFIG_X86_PAE is set */
 
.patch = native_patch,
.banner = default_banner,
===
--- a/arch/i386/mm/fault.c
+++ b/arch/i386/mm/fault.c
@@ -616,8 +616,7 @@ do_sigbus:
force_sig_info_fault(SIGBUS, BUS_ADRERR, address, tsk);
 }
 
-#ifndef CONFIG_X86_PAE
-void vmalloc_sync_all(void)
+void _vmalloc_sync_all(void)
 {
/*
 * Note that races in the updates of insync and start aren't
@@ -628,6 +627,8 @@ void vmalloc_sync_all(void)
static DECLARE_BITMAP(insync, PTRS_PER_PGD);
static unsigned long start = TASK_SIZE;
unsigned long address;
+
+   BUG_ON(SHARED_KERNEL_PMD);
 
BUILD_BUG_ON(TASK_SIZE  ~PGDIR_MASK);
for (address = start; address = TASK_SIZE; address += PGDIR_SIZE) {
@@ -651,4 +652,3 @@ void vmalloc_sync_all(void)
start = address + PGDIR_SIZE;
}
 }
-#endif
===
--- a/arch/i386/mm/pageattr.c
+++ b/arch/i386/mm/pageattr.c
@@ -91,7 +91,7 @@ static void set_pmd_pte(pte_t *kpte, uns
unsigned long flags;
 
set_pte_atomic(kpte, pte);  /* change init_mm */
-   if (PTRS_PER_PMD  1)
+   if (SHARED_KERNEL_PMD)
return;
 
spin_lock_irqsave(pgd_lock, flags);
===
--- a/arch/i386/mm/pgtable.c
+++ b/arch/i386/mm/pgtable.c
@@ -241,31 +241,42 @@ static void pgd_ctor(pgd_t *pgd)
unsigned long flags;
 
if (PTRS_PER_PMD == 1) {
+   /* !PAE, no pagetable sharing */
memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
+
+   clone_pgd_range(pgd + USER_PTRS_PER_PGD,
+   swapper_pg_dir + USER_PTRS_PER_PGD,
+   KERNEL_PGD_PTRS);
+
spin_lock_irqsave(pgd_lock, flags);
-   }
-
-   clone_pgd_range(pgd + USER_PTRS_PER_PGD,
-   swapper_pg_dir + USER_PTRS_PER_PGD,
-   KERNEL_PGD_PTRS);
-
-   if (PTRS_PER_PMD  1)
-   return;
-
-   /* must happen under lock */
-   paravirt_alloc_pd_clone(__pa(pgd)  PAGE_SHIFT,
-   __pa(swapper_pg_dir)  PAGE_SHIFT,
-   USER_PTRS_PER_PGD, PTRS_PER_PGD - USER_PTRS_PER_PGD);
-
-   pgd_list_add(pgd);
-   spin_unlock_irqrestore(pgd_lock, flags);
+
+   /* must happen under lock */
+   paravirt_alloc_pd_clone(__pa(pgd)  PAGE_SHIFT,
+   __pa(swapper_pg_dir)  PAGE_SHIFT,
+   USER_PTRS_PER_PGD,
+   PTRS_PER_PGD - USER_PTRS_PER_PGD);
+
+   pgd_list_add(pgd);
+   spin_unlock_irqrestore(pgd_lock, flags);
+   } else {
+   /* PAE, PMD may be shared */
+   if (SHARED_KERNEL_PMD) {
+   clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
+   swapper_pg_dir + USER_PTRS_PER_PGD,
+   KERNEL_PGD_PTRS);
+   } else {
+   spin_lock_irqsave(pgd_lock, flags);
+   pgd_list_add(pgd);
+   spin_unlock_irqrestore(pgd_lock, flags);
+   }
+   }
 }
 
 static void pgd_dtor(pgd_t *pgd)
 {
unsigned long flags; /* can be called from interrupt context */
 
-   if (PTRS_PER_PMD == 1)
+   if (SHARED_KERNEL_PMD)
return;
 
paravirt_release_pd(__pa(pgd)  PAGE_SHIFT);
@@ -279,19 +290,25 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
int i;
pgd_t *pgd = kmem_cache_alloc(pgd_cache, GFP_KERNEL);
 
-   if (pgd)
+   if