diff options
Diffstat (limited to 'arch/sparc/mm/tlb.c')
| -rw-r--r-- | arch/sparc/mm/tlb.c | 38 | 
1 files changed, 34 insertions, 4 deletions
diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c index ba6ae7ffdc2..272aa4f7657 100644 --- a/arch/sparc/mm/tlb.c +++ b/arch/sparc/mm/tlb.c @@ -24,11 +24,17 @@ static DEFINE_PER_CPU(struct tlb_batch, tlb_batch);  void flush_tlb_pending(void)  {  	struct tlb_batch *tb = &get_cpu_var(tlb_batch); +	struct mm_struct *mm = tb->mm; -	if (tb->tlb_nr) { -		flush_tsb_user(tb); +	if (!tb->tlb_nr) +		goto out; -		if (CTX_VALID(tb->mm->context)) { +	flush_tsb_user(tb); + +	if (CTX_VALID(mm->context)) { +		if (tb->tlb_nr == 1) { +			global_flush_tlb_page(mm, tb->vaddrs[0]); +		} else {  #ifdef CONFIG_SMP  			smp_flush_tlb_pending(tb->mm, tb->tlb_nr,  					      &tb->vaddrs[0]); @@ -37,12 +43,30 @@ void flush_tlb_pending(void)  					    tb->tlb_nr, &tb->vaddrs[0]);  #endif  		} -		tb->tlb_nr = 0;  	} +	tb->tlb_nr = 0; + +out:  	put_cpu_var(tlb_batch);  } +void arch_enter_lazy_mmu_mode(void) +{ +	struct tlb_batch *tb = &__get_cpu_var(tlb_batch); + +	tb->active = 1; +} + +void arch_leave_lazy_mmu_mode(void) +{ +	struct tlb_batch *tb = &__get_cpu_var(tlb_batch); + +	if (tb->tlb_nr) +		flush_tlb_pending(); +	tb->active = 0; +} +  static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr,  			      bool exec)  { @@ -60,6 +84,12 @@ static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr,  		nr = 0;  	} +	if (!tb->active) { +		global_flush_tlb_page(mm, vaddr); +		flush_tsb_user_page(mm, vaddr); +		return; +	} +  	if (nr == 0)  		tb->mm = mm;  |