tlbflush_32.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /*
  2. * TLB flushing operations for SH with an MMU.
  3. *
  4. * Copyright (C) 1999 Niibe Yutaka
  5. * Copyright (C) 2003 Paul Mundt
  6. *
  7. * This file is subject to the terms and conditions of the GNU General Public
  8. * License. See the file "COPYING" in the main directory of this archive
  9. * for more details.
  10. */
  11. #include <linux/mm.h>
  12. #include <asm/mmu_context.h>
  13. #include <asm/tlbflush.h>
  14. void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
  15. {
  16. unsigned int cpu = smp_processor_id();
  17. if (vma->vm_mm && cpu_context(cpu, vma->vm_mm) != NO_CONTEXT) {
  18. unsigned long flags;
  19. unsigned long asid;
  20. unsigned long saved_asid = MMU_NO_ASID;
  21. asid = cpu_asid(cpu, vma->vm_mm);
  22. page &= PAGE_MASK;
  23. local_irq_save(flags);
  24. if (vma->vm_mm != current->mm) {
  25. saved_asid = get_asid();
  26. set_asid(asid);
  27. }
  28. local_flush_tlb_one(asid, page);
  29. if (saved_asid != MMU_NO_ASID)
  30. set_asid(saved_asid);
  31. local_irq_restore(flags);
  32. }
  33. }
  34. void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
  35. unsigned long end)
  36. {
  37. struct mm_struct *mm = vma->vm_mm;
  38. unsigned int cpu = smp_processor_id();
  39. if (cpu_context(cpu, mm) != NO_CONTEXT) {
  40. unsigned long flags;
  41. int size;
  42. local_irq_save(flags);
  43. size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
  44. if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */
  45. cpu_context(cpu, mm) = NO_CONTEXT;
  46. if (mm == current->mm)
  47. activate_context(mm, cpu);
  48. } else {
  49. unsigned long asid;
  50. unsigned long saved_asid = MMU_NO_ASID;
  51. asid = cpu_asid(cpu, mm);
  52. start &= PAGE_MASK;
  53. end += (PAGE_SIZE - 1);
  54. end &= PAGE_MASK;
  55. if (mm != current->mm) {
  56. saved_asid = get_asid();
  57. set_asid(asid);
  58. }
  59. while (start < end) {
  60. local_flush_tlb_one(asid, start);
  61. start += PAGE_SIZE;
  62. }
  63. if (saved_asid != MMU_NO_ASID)
  64. set_asid(saved_asid);
  65. }
  66. local_irq_restore(flags);
  67. }
  68. }
  69. void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
  70. {
  71. unsigned int cpu = smp_processor_id();
  72. unsigned long flags;
  73. int size;
  74. local_irq_save(flags);
  75. size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
  76. if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */
  77. local_flush_tlb_all();
  78. } else {
  79. unsigned long asid;
  80. unsigned long saved_asid = get_asid();
  81. asid = cpu_asid(cpu, &init_mm);
  82. start &= PAGE_MASK;
  83. end += (PAGE_SIZE - 1);
  84. end &= PAGE_MASK;
  85. set_asid(asid);
  86. while (start < end) {
  87. local_flush_tlb_one(asid, start);
  88. start += PAGE_SIZE;
  89. }
  90. set_asid(saved_asid);
  91. }
  92. local_irq_restore(flags);
  93. }
  94. void local_flush_tlb_mm(struct mm_struct *mm)
  95. {
  96. unsigned int cpu = smp_processor_id();
  97. /* Invalidate all TLB of this process. */
  98. /* Instead of invalidating each TLB, we get new MMU context. */
  99. if (cpu_context(cpu, mm) != NO_CONTEXT) {
  100. unsigned long flags;
  101. local_irq_save(flags);
  102. cpu_context(cpu, mm) = NO_CONTEXT;
  103. if (mm == current->mm)
  104. activate_context(mm, cpu);
  105. local_irq_restore(flags);
  106. }
  107. }
  108. void __flush_tlb_global(void)
  109. {
  110. unsigned long flags;
  111. local_irq_save(flags);
  112. /*
  113. * This is the most destructive of the TLB flushing options,
  114. * and will tear down all of the UTLB/ITLB mappings, including
  115. * wired entries.
  116. */
  117. __raw_writel(__raw_readl(MMUCR) | MMUCR_TI, MMUCR);
  118. local_irq_restore(flags);
  119. }