2006-09-27 15:13:36 +09:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								/*
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								 * TLB flushing operations for SH with an MMU.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								 *
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								 *  Copyright (C) 1999  Niibe Yutaka
							 | 
						
					
						
							
								
									
										
										
										
											2007-03-05 19:46:47 +09:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								 *  Copyright (C) 2003  Paul Mundt
							 | 
						
					
						
							
								
									
										
										
										
											2006-09-27 15:13:36 +09:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								 *
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								 * This file is subject to the terms and conditions of the GNU General Public
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								 * License.  See the file "COPYING" in the main directory of this archive
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								 * for more details.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								 */
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#include <linux/mm.h>
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#include <asm/mmu_context.h>
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#include <asm/tlbflush.h>
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2006-12-25 19:28:54 +09:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
							 | 
						
					
						
							
								
									
										
										
										
											2006-09-27 15:13:36 +09:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								{
							 | 
						
					
						
							
								
									
										
										
										
											2006-12-25 09:51:47 +09:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
									unsigned int cpu = smp_processor_id();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									if (vma->vm_mm && cpu_context(cpu, vma->vm_mm) != NO_CONTEXT) {
							 | 
						
					
						
							
								
									
										
										
										
											2006-09-27 15:13:36 +09:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										unsigned long flags;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										unsigned long asid;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										unsigned long saved_asid = MMU_NO_ASID;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2006-12-25 09:51:47 +09:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
										asid = cpu_asid(cpu, vma->vm_mm);
							 | 
						
					
						
							
								
									
										
										
										
											2006-09-27 15:13:36 +09:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										page &= PAGE_MASK;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										local_irq_save(flags);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										if (vma->vm_mm != current->mm) {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											saved_asid = get_asid();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											set_asid(asid);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										}
							 | 
						
					
						
							
								
									
										
										
										
											2006-12-25 19:37:56 +09:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
										local_flush_tlb_one(asid, page);
							 | 
						
					
						
							
								
									
										
										
										
											2006-09-27 15:13:36 +09:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										if (saved_asid != MMU_NO_ASID)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											set_asid(saved_asid);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										local_irq_restore(flags);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2006-12-25 19:28:54 +09:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											   unsigned long end)
							 | 
						
					
						
							
								
									
										
										
										
											2006-09-27 15:13:36 +09:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								{
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									struct mm_struct *mm = vma->vm_mm;
							 | 
						
					
						
							
								
									
										
										
										
											2006-12-25 09:51:47 +09:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
									unsigned int cpu = smp_processor_id();
							 | 
						
					
						
							
								
									
										
										
										
											2006-09-27 15:13:36 +09:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2006-12-25 09:51:47 +09:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
									if (cpu_context(cpu, mm) != NO_CONTEXT) {
							 | 
						
					
						
							
								
									
										
										
										
											2006-09-27 15:13:36 +09:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										unsigned long flags;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										int size;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										local_irq_save(flags);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */
							 | 
						
					
						
							
								
									
										
										
										
											2006-12-25 09:51:47 +09:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
											cpu_context(cpu, mm) = NO_CONTEXT;
							 | 
						
					
						
							
								
									
										
										
										
											2006-09-27 15:13:36 +09:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
											if (mm == current->mm)
							 | 
						
					
						
							
								
									
										
										
										
											2006-12-25 09:51:47 +09:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
												activate_context(mm, cpu);
							 | 
						
					
						
							
								
									
										
										
										
											2006-09-27 15:13:36 +09:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										} else {
							 | 
						
					
						
							
								
									
										
										
										
											2006-09-27 18:33:49 +09:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
											unsigned long asid;
							 | 
						
					
						
							
								
									
										
										
										
											2006-09-27 15:13:36 +09:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
											unsigned long saved_asid = MMU_NO_ASID;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2006-12-25 09:51:47 +09:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
											asid = cpu_asid(cpu, mm);
							 | 
						
					
						
							
								
									
										
										
										
											2006-09-27 15:13:36 +09:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
											start &= PAGE_MASK;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											end += (PAGE_SIZE - 1);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											end &= PAGE_MASK;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											if (mm != current->mm) {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
												saved_asid = get_asid();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
												set_asid(asid);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											while (start < end) {
							 | 
						
					
						
							
								
									
										
										
										
											2006-12-25 19:37:56 +09:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
												local_flush_tlb_one(asid, start);
							 | 
						
					
						
							
								
									
										
										
										
											2006-09-27 15:13:36 +09:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
												start += PAGE_SIZE;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											if (saved_asid != MMU_NO_ASID)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
												set_asid(saved_asid);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										local_irq_restore(flags);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2006-12-25 19:28:54 +09:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
							 | 
						
					
						
							
								
									
										
										
										
											2006-09-27 15:13:36 +09:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								{
							 | 
						
					
						
							
								
									
										
										
										
											2006-12-25 09:51:47 +09:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
									unsigned int cpu = smp_processor_id();
							 | 
						
					
						
							
								
									
										
										
										
											2006-09-27 15:13:36 +09:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
									unsigned long flags;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									int size;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									local_irq_save(flags);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */
							 | 
						
					
						
							
								
									
										
										
										
											2006-12-25 19:28:54 +09:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
										local_flush_tlb_all();
							 | 
						
					
						
							
								
									
										
										
										
											2006-09-27 15:13:36 +09:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
									} else {
							 | 
						
					
						
							
								
									
										
										
										
											2006-09-27 18:33:49 +09:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
										unsigned long asid;
							 | 
						
					
						
							
								
									
										
										
										
											2006-09-27 15:13:36 +09:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										unsigned long saved_asid = get_asid();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2006-12-25 09:51:47 +09:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
										asid = cpu_asid(cpu, &init_mm);
							 | 
						
					
						
							
								
									
										
										
										
											2006-09-27 15:13:36 +09:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										start &= PAGE_MASK;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										end += (PAGE_SIZE - 1);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										end &= PAGE_MASK;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										set_asid(asid);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										while (start < end) {
							 | 
						
					
						
							
								
									
										
										
										
											2006-12-25 19:37:56 +09:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
											local_flush_tlb_one(asid, start);
							 | 
						
					
						
							
								
									
										
										
										
											2006-09-27 15:13:36 +09:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
											start += PAGE_SIZE;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										set_asid(saved_asid);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									local_irq_restore(flags);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2006-12-25 19:28:54 +09:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								void local_flush_tlb_mm(struct mm_struct *mm)
							 | 
						
					
						
							
								
									
										
										
										
											2006-09-27 15:13:36 +09:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								{
							 | 
						
					
						
							
								
									
										
										
										
											2006-12-25 09:51:47 +09:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
									unsigned int cpu = smp_processor_id();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2006-09-27 15:13:36 +09:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
									/* Invalidate all TLB of this process. */
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									/* Instead of invalidating each TLB, we get new MMU context. */
							 | 
						
					
						
							
								
									
										
										
										
											2006-12-25 09:51:47 +09:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
									if (cpu_context(cpu, mm) != NO_CONTEXT) {
							 | 
						
					
						
							
								
									
										
										
										
											2006-09-27 15:13:36 +09:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										unsigned long flags;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										local_irq_save(flags);
							 | 
						
					
						
							
								
									
										
										
										
											2006-12-25 09:51:47 +09:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
										cpu_context(cpu, mm) = NO_CONTEXT;
							 | 
						
					
						
							
								
									
										
										
										
											2006-09-27 15:13:36 +09:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										if (mm == current->mm)
							 | 
						
					
						
							
								
									
										
										
										
											2006-12-25 09:51:47 +09:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
											activate_context(mm, cpu);
							 | 
						
					
						
							
								
									
										
										
										
											2006-09-27 15:13:36 +09:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										local_irq_restore(flags);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								}
							 | 
						
					
						
							
								
									
										
										
										
											2010-07-02 15:44:09 +09:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								void __flush_tlb_global(void)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								{
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									unsigned long flags;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									local_irq_save(flags);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									/*
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									 * This is the most destructive of the TLB flushing options,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									 * and will tear down all of the UTLB/ITLB mappings, including
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									 * wired entries.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									 */
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									__raw_writel(__raw_readl(MMUCR) | MMUCR_TI, MMUCR);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									local_irq_restore(flags);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								}
							 |