mmu_context.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /*
  2. * Switch an MMU context.
  3. *
  4. * This file is subject to the terms and conditions of the GNU General Public
  5. * License. See the file "COPYING" in the main directory of this archive
  6. * for more details.
  7. *
  8. * Copyright (C) 2001 - 2013 Tensilica Inc.
  9. */
  10. #ifndef _XTENSA_MMU_CONTEXT_H
  11. #define _XTENSA_MMU_CONTEXT_H
  12. #ifndef CONFIG_MMU
  13. #include <asm/nommu_context.h>
  14. #else
  15. #include <linux/stringify.h>
  16. #include <linux/sched.h>
  17. #include <linux/mm_types.h>
  18. #include <linux/pgtable.h>
  19. #include <asm/vectors.h>
  20. #include <asm/cacheflush.h>
  21. #include <asm/tlbflush.h>
  22. #include <asm-generic/mm_hooks.h>
  23. #include <asm-generic/percpu.h>
  24. #if (XCHAL_HAVE_TLBS != 1)
  25. # error "Linux must have an MMU!"
  26. #endif
  27. DECLARE_PER_CPU(unsigned long, asid_cache);
  28. #define cpu_asid_cache(cpu) per_cpu(asid_cache, cpu)
  29. /*
  30. * NO_CONTEXT is the invalid ASID value that we don't ever assign to
  31. * any user or kernel context. We use the reserved values in the
  32. * ASID_INSERT macro below.
  33. *
  34. * 0 invalid
  35. * 1 kernel
  36. * 2 reserved
  37. * 3 reserved
  38. * 4...255 available
  39. */
  40. #define NO_CONTEXT 0
  41. #define ASID_USER_FIRST 4
  42. #define ASID_MASK ((1 << XCHAL_MMU_ASID_BITS) - 1)
  43. #define ASID_INSERT(x) (0x03020001 | (((x) & ASID_MASK) << 8))
  44. void init_mmu(void);
  45. void init_kio(void);
  46. static inline void set_rasid_register (unsigned long val)
  47. {
  48. __asm__ __volatile__ (" wsr %0, rasid\n\t"
  49. " isync\n" : : "a" (val));
  50. }
  51. static inline unsigned long get_rasid_register (void)
  52. {
  53. unsigned long tmp;
  54. __asm__ __volatile__ (" rsr %0, rasid\n\t" : "=a" (tmp));
  55. return tmp;
  56. }
  57. static inline void get_new_mmu_context(struct mm_struct *mm, unsigned int cpu)
  58. {
  59. unsigned long asid = cpu_asid_cache(cpu);
  60. if ((++asid & ASID_MASK) == 0) {
  61. /*
  62. * Start new asid cycle; continue counting with next
  63. * incarnation bits; skipping over 0, 1, 2, 3.
  64. */
  65. local_flush_tlb_all();
  66. asid += ASID_USER_FIRST;
  67. }
  68. cpu_asid_cache(cpu) = asid;
  69. mm->context.asid[cpu] = asid;
  70. mm->context.cpu = cpu;
  71. }
  72. static inline void get_mmu_context(struct mm_struct *mm, unsigned int cpu)
  73. {
  74. /*
  75. * Check if our ASID is of an older version and thus invalid.
  76. */
  77. if (mm) {
  78. unsigned long asid = mm->context.asid[cpu];
  79. if (asid == NO_CONTEXT ||
  80. ((asid ^ cpu_asid_cache(cpu)) & ~ASID_MASK))
  81. get_new_mmu_context(mm, cpu);
  82. }
  83. }
  84. static inline void activate_context(struct mm_struct *mm, unsigned int cpu)
  85. {
  86. get_mmu_context(mm, cpu);
  87. set_rasid_register(ASID_INSERT(mm->context.asid[cpu]));
  88. invalidate_page_directory();
  89. }
  90. /*
  91. * Initialize the context related info for a new mm_struct
  92. * instance. Valid cpu values are 0..(NR_CPUS-1), so initializing
  93. * to -1 says the process has never run on any core.
  94. */
  95. #define init_new_context init_new_context
  96. static inline int init_new_context(struct task_struct *tsk,
  97. struct mm_struct *mm)
  98. {
  99. int cpu;
  100. for_each_possible_cpu(cpu) {
  101. mm->context.asid[cpu] = NO_CONTEXT;
  102. }
  103. mm->context.cpu = -1;
  104. return 0;
  105. }
  106. static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
  107. struct task_struct *tsk)
  108. {
  109. unsigned int cpu = smp_processor_id();
  110. int migrated = next->context.cpu != cpu;
  111. /* Flush the icache if we migrated to a new core. */
  112. if (migrated) {
  113. __invalidate_icache_all();
  114. next->context.cpu = cpu;
  115. }
  116. if (migrated || prev != next)
  117. activate_context(next, cpu);
  118. }
  119. /*
  120. * Destroy context related info for an mm_struct that is about
  121. * to be put to rest.
  122. */
  123. #define destroy_context destroy_context
  124. static inline void destroy_context(struct mm_struct *mm)
  125. {
  126. invalidate_page_directory();
  127. }
  128. #include <asm-generic/mmu_context.h>
  129. #endif /* CONFIG_MMU */
  130. #endif /* _XTENSA_MMU_CONTEXT_H */