home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / src / linux-headers-2.6.17-6 / include / asm-sh / mmu_context.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  4.9 KB  |  207 lines

  1. /*
  2.  * Copyright (C) 1999 Niibe Yutaka
  3.  * Copyright (C) 2003 Paul Mundt
  4.  *
  5.  * ASID handling idea taken from MIPS implementation.
  6.  */
  7. #ifndef __ASM_SH_MMU_CONTEXT_H
  8. #define __ASM_SH_MMU_CONTEXT_H
  9. #ifdef __KERNEL__
  10.  
  11. #include <asm/cpu/mmu_context.h>
  12. #include <asm/tlbflush.h>
  13. #include <asm/pgalloc.h>
  14. #include <asm/uaccess.h>
  15. #include <asm/io.h>
  16.  
  17. /*
  18.  * The MMU "context" consists of two things:
  19.  *    (a) TLB cache version (or round, cycle whatever expression you like)
  20.  *    (b) ASID (Address Space IDentifier)
  21.  */
  22.  
  23. /*
  24.  * Cache of MMU context last used.
  25.  */
  26. extern unsigned long mmu_context_cache;
  27.  
  28. #define MMU_CONTEXT_ASID_MASK        0x000000ff
  29. #define MMU_CONTEXT_VERSION_MASK    0xffffff00
  30. #define MMU_CONTEXT_FIRST_VERSION    0x00000100
  31. #define NO_CONTEXT            0
  32.  
  33. /* ASID is 8-bit value, so it can't be 0x100 */
  34. #define MMU_NO_ASID            0x100
  35.  
  36. /*
  37.  * Virtual Page Number mask
  38.  */
  39. #define MMU_VPN_MASK    0xfffff000
  40.  
  41. #ifdef CONFIG_MMU
  42. /*
  43.  * Get MMU context if needed.
  44.  */
  45. static __inline__ void
  46. get_mmu_context(struct mm_struct *mm)
  47. {
  48.     extern void flush_tlb_all(void);
  49.     unsigned long mc = mmu_context_cache;
  50.  
  51.     /* Check if we have old version of context. */
  52.     if (((mm->context ^ mc) & MMU_CONTEXT_VERSION_MASK) == 0)
  53.         /* It's up to date, do nothing */
  54.         return;
  55.  
  56.     /* It's old, we need to get new context with new version. */
  57.     mc = ++mmu_context_cache;
  58.     if (!(mc & MMU_CONTEXT_ASID_MASK)) {
  59.         /*
  60.          * We exhaust ASID of this version.
  61.          * Flush all TLB and start new cycle.
  62.          */
  63.         flush_tlb_all();
  64.         /*
  65.          * Fix version; Note that we avoid version #0
  66.          * to distingush NO_CONTEXT.
  67.          */
  68.         if (!mc)
  69.             mmu_context_cache = mc = MMU_CONTEXT_FIRST_VERSION;
  70.     }
  71.     mm->context = mc;
  72. }
  73.  
  74. /*
  75.  * Initialize the context related info for a new mm_struct
  76.  * instance.
  77.  */
  78. static __inline__ int init_new_context(struct task_struct *tsk,
  79.                        struct mm_struct *mm)
  80. {
  81.     mm->context = NO_CONTEXT;
  82.  
  83.     return 0;
  84. }
  85.  
  86. /*
  87.  * Destroy context related info for an mm_struct that is about
  88.  * to be put to rest.
  89.  */
  90. static __inline__ void destroy_context(struct mm_struct *mm)
  91. {
  92.     /* Do nothing */
  93. }
  94.  
  95. static __inline__ void set_asid(unsigned long asid)
  96. {
  97.     unsigned long __dummy;
  98.  
  99.     __asm__ __volatile__ ("mov.l    %2, %0\n\t"
  100.                   "and    %3, %0\n\t"
  101.                   "or    %1, %0\n\t"
  102.                   "mov.l    %0, %2"
  103.                   : "=&r" (__dummy)
  104.                   : "r" (asid), "m" (__m(MMU_PTEH)),
  105.                     "r" (0xffffff00));
  106. }
  107.  
  108. static __inline__ unsigned long get_asid(void)
  109. {
  110.     unsigned long asid;
  111.  
  112.     __asm__ __volatile__ ("mov.l    %1, %0"
  113.                   : "=r" (asid)
  114.                   : "m" (__m(MMU_PTEH)));
  115.     asid &= MMU_CONTEXT_ASID_MASK;
  116.     return asid;
  117. }
  118.  
  119. /*
  120.  * After we have set current->mm to a new value, this activates
  121.  * the context for the new mm so we see the new mappings.
  122.  */
  123. static __inline__ void activate_context(struct mm_struct *mm)
  124. {
  125.     get_mmu_context(mm);
  126.     set_asid(mm->context & MMU_CONTEXT_ASID_MASK);
  127. }
  128.  
  129. /* MMU_TTB can be used for optimizing the fault handling.
  130.    (Currently not used) */
  131. static __inline__ void switch_mm(struct mm_struct *prev,
  132.                  struct mm_struct *next,
  133.                  struct task_struct *tsk)
  134. {
  135.     if (likely(prev != next)) {
  136.         unsigned long __pgdir = (unsigned long)next->pgd;
  137.  
  138.         __asm__ __volatile__("mov.l    %0, %1"
  139.                      : /* no output */
  140.                      : "r" (__pgdir), "m" (__m(MMU_TTB)));
  141.         activate_context(next);
  142.     }
  143. }
  144.  
  145. #define deactivate_mm(tsk,mm)    do { } while (0)
  146.  
  147. #define activate_mm(prev, next) \
  148.     switch_mm((prev),(next),NULL)
  149.  
  150. static __inline__ void
  151. enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
  152. {
  153. }
  154. #else /* !CONFIG_MMU */
  155. #define get_mmu_context(mm)        do { } while (0)
  156. #define init_new_context(tsk,mm)    (0)
  157. #define destroy_context(mm)        do { } while (0)
  158. #define set_asid(asid)            do { } while (0)
  159. #define get_asid()            (0)
  160. #define activate_context(mm)        do { } while (0)
  161. #define switch_mm(prev,next,tsk)    do { } while (0)
  162. #define deactivate_mm(tsk,mm)        do { } while (0)
  163. #define activate_mm(prev,next)        do { } while (0)
  164. #define enter_lazy_tlb(mm,tsk)        do { } while (0)
  165. #endif /* CONFIG_MMU */
  166.  
  167. #if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4)
  168. /*
  169.  * If this processor has an MMU, we need methods to turn it off/on ..
  170.  * paging_init() will also have to be updated for the processor in
  171.  * question.
  172.  */
  173. static inline void enable_mmu(void)
  174. {
  175.     /* Enable MMU */
  176.     ctrl_outl(MMU_CONTROL_INIT, MMUCR);
  177.  
  178.     /* The manual suggests doing some nops after turning on the MMU */
  179.     __asm__ __volatile__ ("nop;nop;nop;nop;nop;nop;nop;nop\n\t");
  180.  
  181.     if (mmu_context_cache == NO_CONTEXT)
  182.         mmu_context_cache = MMU_CONTEXT_FIRST_VERSION;
  183.  
  184.     set_asid(mmu_context_cache & MMU_CONTEXT_ASID_MASK);
  185. }
  186.  
  187. static inline void disable_mmu(void)
  188. {
  189.     unsigned long cr;
  190.  
  191.     cr = ctrl_inl(MMUCR);
  192.     cr &= ~MMU_CONTROL_INIT;
  193.     ctrl_outl(cr, MMUCR);
  194.     __asm__ __volatile__ ("nop;nop;nop;nop;nop;nop;nop;nop\n\t");
  195. }
  196. #else
  197. /*
  198.  * MMU control handlers for processors lacking memory
  199.  * management hardware.
  200.  */
  201. #define enable_mmu()    do { BUG(); } while (0)
  202. #define disable_mmu()    do { BUG(); } while (0)
  203. #endif
  204.  
  205. #endif /* __KERNEL__ */
  206. #endif /* __ASM_SH_MMU_CONTEXT_H */
  207.