sparc64 current tlb flush needs it's per-cpu list of vaddr's. This patch disconnect that from the mmu_gather, allowing sparc64 to use the generic implementation of the later for now.
This is somewhat temporary. It allows to keep sparc64 working while I'm doing surgery on mmu_gather. Once the later goes fully stack based and provide a non-percpu way of storing the page list along with arch specific informations, I'll be able to reconnect sparc64 to it (and get rid of the get_cpu/put_cpu and associated preempt disabling). Signed-off-by: Benjamin Herrenschmidt <[EMAIL PROTECTED]> --- arch/sparc64/kernel/smp.c | 2 arch/sparc64/mm/tlb.c | 43 ++++++++++-------- arch/sparc64/mm/tsb.c | 6 +- arch/sparc64/mm/ultra.S | 12 ++--- include/asm-sparc64/system.h | 2 include/asm-sparc64/tlb.h | 95 +++++++++-------------------------------- include/asm-sparc64/tlbflush.h | 4 - 7 files changed, 59 insertions(+), 105 deletions(-) Index: linux-work/arch/sparc64/mm/tlb.c =================================================================== --- linux-work.orig/arch/sparc64/mm/tlb.c 2007-07-27 18:06:08.000000000 +1000 +++ linux-work/arch/sparc64/mm/tlb.c 2007-07-27 18:06:44.000000000 +1000 @@ -19,35 +19,38 @@ /* Heavily inspired by the ppc64 code. */ -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers) = { 0, }; +DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); +DEFINE_PER_CPU(struct tlb_batch, tlb_batch); -void flush_tlb_pending(void) +void __flush_tlb_pending(struct tlb_batch *mp) { - struct mmu_gather *mp = &__get_cpu_var(mmu_gathers); - - preempt_disable(); - - if (mp->tlb_nr) { + if (mp->nr) { flush_tsb_user(mp); if (CTX_VALID(mp->mm->context)) { #ifdef CONFIG_SMP - smp_flush_tlb_pending(mp->mm, mp->tlb_nr, + smp_flush_tlb_pending(mp->mm, mp->nr, &mp->vaddrs[0]); #else - __flush_tlb_pending(CTX_HWBITS(mp->mm->context), - mp->tlb_nr, &mp->vaddrs[0]); + local_flush_tlb_pending(CTX_HWBITS(mp->mm->context), + mp->nr, &mp->vaddrs[0]); #endif } - mp->tlb_nr = 0; + mp->nr = 0; } +} + +void flush_tlb_pending(void) +{ + struct tlb_batch *mp = &get_cpu_var(tlb_batch); - preempt_enable(); + __flush_tlb_pending(mp); + put_cpu_var(tlb_batch); } void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, pte_t *ptep, pte_t orig) { - struct mmu_gather *mp = &__get_cpu_var(mmu_gathers); + struct tlb_batch *mp; unsigned long nr; vaddr &= PAGE_MASK; @@ -79,13 +82,17 @@ void tlb_batch_add(struct mm_struct *mm, no_cache_flush: - if (mp->fullmm) + if (test_bit(MMF_DEAD, &mm->flags)) return; - nr = mp->tlb_nr; + /* we are called with enough spinlocks held to make + * preempt disable useless here + */ + mp = &__get_cpu_var(tlb_batch); + nr = mp->nr; if (unlikely(nr != 0 && mm != mp->mm)) { - flush_tlb_pending(); + __flush_tlb_pending(mp); nr = 0; } @@ -93,7 +100,7 @@ no_cache_flush: mp->mm = mm; mp->vaddrs[nr] = vaddr; - mp->tlb_nr = ++nr; + mp->nr = ++nr; if (nr >= TLB_BATCH_NR) - flush_tlb_pending(); + __flush_tlb_pending(mp); } Index: linux-work/arch/sparc64/mm/tsb.c =================================================================== --- linux-work.orig/arch/sparc64/mm/tsb.c 2007-07-27 18:06:08.000000000 +1000 +++ linux-work/arch/sparc64/mm/tsb.c 2007-07-27 18:06:44.000000000 +1000 @@ -47,11 +47,11 @@ void flush_tsb_kernel_range(unsigned lon } } -static void __flush_tsb_one(struct mmu_gather *mp, unsigned long hash_shift, unsigned long tsb, unsigned long nentries) +static void __flush_tsb_one(struct tlb_batch *mp, unsigned long hash_shift, unsigned long tsb, unsigned long nentries) { unsigned long i; - for (i = 0; i < mp->tlb_nr; i++) { + for (i = 0; i < mp->nr; i++) { unsigned long v = mp->vaddrs[i]; unsigned long tag, ent, hash; @@ -65,7 +65,7 @@ static void __flush_tsb_one(struct mmu_g } } -void flush_tsb_user(struct mmu_gather *mp) +void flush_tsb_user(struct tlb_batch *mp) { struct mm_struct *mm = mp->mm; unsigned long nentries, base, flags; Index: linux-work/arch/sparc64/mm/ultra.S =================================================================== --- linux-work.orig/arch/sparc64/mm/ultra.S 2007-07-27 18:06:08.000000000 +1000 +++ linux-work/arch/sparc64/mm/ultra.S 2007-07-27 18:06:44.000000000 +1000 @@ -52,8 +52,8 @@ __flush_tlb_mm: /* 18 insns */ nop .align 32 - .globl __flush_tlb_pending -__flush_tlb_pending: /* 26 insns */ + .globl local_flush_tlb_pending +local_flush_tlb_pending: /* 26 insns */ /* %o0 = context, %o1 = nr, %o2 = vaddrs[] */ rdpr %pstate, %g7 sllx %o1, 3, %o1 @@ -346,8 +346,8 @@ cheetah_patch_cachetlbops: call tlb_patch_one mov 19, %o2 - sethi %hi(__flush_tlb_pending), %o0 - or %o0, %lo(__flush_tlb_pending), %o0 + sethi %hi(local_flush_tlb_pending), %o0 + or %o0, %lo(local_flush_tlb_pending), %o0 sethi %hi(__cheetah_flush_tlb_pending), %o1 or %o1, %lo(__cheetah_flush_tlb_pending), %o1 call tlb_patch_one @@ -699,8 +699,8 @@ hypervisor_patch_cachetlbops: call tlb_patch_one mov 10, %o2 - sethi %hi(__flush_tlb_pending), %o0 - or %o0, %lo(__flush_tlb_pending), %o0 + sethi %hi(local_flush_tlb_pending), %o0 + or %o0, %lo(local_flush_tlb_pending), %o0 sethi %hi(__hypervisor_flush_tlb_pending), %o1 or %o1, %lo(__hypervisor_flush_tlb_pending), %o1 call tlb_patch_one Index: linux-work/include/asm-sparc64/tlb.h =================================================================== --- linux-work.orig/include/asm-sparc64/tlb.h 2007-07-27 18:06:08.000000000 +1000 +++ linux-work/include/asm-sparc64/tlb.h 2007-07-27 18:06:44.000000000 +1000 @@ -7,62 +7,38 @@ #include <asm/tlbflush.h> #include <asm/mmu_context.h> -#define TLB_BATCH_NR 192 +#define tlb_flush(mp) \ +do { \ + if (!test_bit(MMF_DEAD, &mp->mm->flags)) \ + flush_tlb_pending(); \ +} while(0) -/* - * For UP we don't need to worry about TLB flush - * and page free order so much.. - */ -#ifdef CONFIG_SMP - #define FREE_PTE_NR 506 - #define tlb_fast_mode(bp) ((bp)->pages_nr == ~0U) -#else - #define FREE_PTE_NR 1 - #define tlb_fast_mode(bp) 1 -#endif +#include <asm-generic/tlb.h> + +#define TLB_BATCH_NR 192 -struct mmu_gather { +struct tlb_batch { struct mm_struct *mm; - unsigned int pages_nr; - unsigned int need_flush; - unsigned int fullmm; - unsigned int tlb_nr; unsigned long vaddrs[TLB_BATCH_NR]; - struct page *pages[FREE_PTE_NR]; + unsigned int nr; }; - -DECLARE_PER_CPU(struct mmu_gather, mmu_gathers); +DECLARE_PER_CPU(struct tlb_batch, tlb_batch); #ifdef CONFIG_SMP extern void smp_flush_tlb_pending(struct mm_struct *, unsigned long, unsigned long *); #endif -extern void __flush_tlb_pending(unsigned long, unsigned long, unsigned long *); +extern void local_flush_tlb_pending(unsigned long, unsigned long, unsigned long *); +extern void __flush_tlb_pending(struct tlb_batch *mp); extern void flush_tlb_pending(void); -static inline struct mmu_gather *tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush) -{ - struct mmu_gather *mp = &get_cpu_var(mmu_gathers); - - BUG_ON(mp->tlb_nr); - - mp->mm = mm; - mp->pages_nr = num_online_cpus() > 1 ? 0U : ~0U; - mp->fullmm = full_mm_flush; - - return mp; -} - - -static inline void tlb_flush_mmu(struct mmu_gather *mp) +/* for use by _switch() */ +static inline void check_flush_tlb_pending(void) { - if (mp->need_flush) { - free_pages_and_swap_cache(mp->pages, mp->pages_nr); - mp->pages_nr = 0; - mp->need_flush = 0; - } - + struct tlb_batch *mp = &__get_cpu_var(tlb_batch); + if (mp->nr) + __flush_tlb_pending(mp); } #ifdef CONFIG_SMP @@ -72,39 +48,10 @@ extern void smp_flush_tlb_mm(struct mm_s #define do_flush_tlb_mm(mm) __flush_tlb_mm(CTX_HWBITS(mm->context), SECONDARY_CONTEXT) #endif -static inline void tlb_finish_mmu(struct mmu_gather *mp, unsigned long start, unsigned long end) -{ - tlb_flush_mmu(mp); - - if (mp->fullmm) - mp->fullmm = 0; - else - flush_tlb_pending(); - - /* keep the page table cache within bounds */ - check_pgt_cache(); - - put_cpu_var(mmu_gathers); -} - -static inline void tlb_remove_page(struct mmu_gather *mp, struct page *page) -{ - if (tlb_fast_mode(mp)) { - free_page_and_swap_cache(page); - return; - } - mp->need_flush = 1; - mp->pages[mp->pages_nr++] = page; - if (mp->pages_nr >= FREE_PTE_NR) - tlb_flush_mmu(mp); -} - -#define tlb_remove_tlb_entry(mp,ptep,addr) do { } while (0) -#define pte_free_tlb(mp,ptepage) pte_free(ptepage) -#define pmd_free_tlb(mp,pmdp) pmd_free(pmdp) -#define pud_free_tlb(tlb,pudp) __pud_free_tlb(tlb,pudp) +#define __tlb_remove_tlb_entry(mp,ptep,addr) do { } while (0) +#define __pte_free_tlb(mp,ptepage) pte_free(ptepage) +#define __pmd_free_tlb(mp,pmdp) pmd_free(pmdp) -#define tlb_migrate_finish(mm) do { } while (0) #define tlb_start_vma(tlb, vma) do { } while (0) #define tlb_end_vma(tlb, vma) do { } while (0) Index: linux-work/include/asm-sparc64/tlbflush.h =================================================================== --- linux-work.orig/include/asm-sparc64/tlbflush.h 2007-07-27 18:06:08.000000000 +1000 +++ linux-work/include/asm-sparc64/tlbflush.h 2007-07-27 18:06:44.000000000 +1000 @@ -5,9 +5,9 @@ #include <asm/mmu_context.h> /* TSB flush operations. */ -struct mmu_gather; +struct tlb_batch; extern void flush_tsb_kernel_range(unsigned long start, unsigned long end); -extern void flush_tsb_user(struct mmu_gather *mp); +extern void flush_tsb_user(struct tlb_batch *mp); /* TLB flush operations. */ Index: linux-work/arch/sparc64/kernel/smp.c =================================================================== --- linux-work.orig/arch/sparc64/kernel/smp.c 2007-07-27 18:06:08.000000000 +1000 +++ linux-work/arch/sparc64/kernel/smp.c 2007-07-27 18:06:44.000000000 +1000 @@ -1142,7 +1142,7 @@ void smp_flush_tlb_pending(struct mm_str ctx, nr, (unsigned long) vaddrs, mm->cpu_vm_mask); - __flush_tlb_pending(ctx, nr, vaddrs); + local_flush_tlb_pending(ctx, nr, vaddrs); put_cpu(); } Index: linux-work/include/asm-sparc64/system.h =================================================================== --- linux-work.orig/include/asm-sparc64/system.h 2007-07-27 18:06:08.000000000 +1000 +++ linux-work/include/asm-sparc64/system.h 2007-07-27 18:06:44.000000000 +1000 @@ -151,7 +151,7 @@ do { if (test_thread_flag(TIF_PERFCTR)) current_thread_info()->kernel_cntd0 += (unsigned int)(__tmp);\ current_thread_info()->kernel_cntd1 += ((__tmp) >> 32); \ } \ - flush_tlb_pending(); \ + check_flush_tlb_pending(); \ save_and_clear_fpu(); \ /* If you are tempted to conditionalize the following */ \ /* so that ASI is only written if it changes, think again. */ \ - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/