[patch 08/21] Xen-paravirt: Allow paravirt backend to choose kernel PMD sharing
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
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