Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mmu_context.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2004-2006 Atmel Corporation
3  *
4  * ASID handling taken from SH implementation.
5  * Copyright (C) 1999 Niibe Yutaka
6  * Copyright (C) 2003 Paul Mundt
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  */
12 #ifndef __ASM_AVR32_MMU_CONTEXT_H
13 #define __ASM_AVR32_MMU_CONTEXT_H
14 
15 #include <asm/tlbflush.h>
16 #include <asm/sysreg.h>
17 #include <asm-generic/mm_hooks.h>
18 
19 /*
20  * The MMU "context" consists of two things:
21  * (a) TLB cache version
22  * (b) ASID (Address Space IDentifier)
23  */
24 #define MMU_CONTEXT_ASID_MASK 0x000000ff
25 #define MMU_CONTEXT_VERSION_MASK 0xffffff00
26 #define MMU_CONTEXT_FIRST_VERSION 0x00000100
27 #define NO_CONTEXT 0
28 
29 #define MMU_NO_ASID 0x100
30 
31 /* Virtual Page Number mask */
32 #define MMU_VPN_MASK 0xfffff000
33 
34 /* Cache of MMU context last used */
35 extern unsigned long mmu_context_cache;
36 
37 /*
38  * Get MMU context if needed
39  */
40 static inline void
41 get_mmu_context(struct mm_struct *mm)
42 {
43  unsigned long mc = mmu_context_cache;
44 
45  if (((mm->context ^ mc) & MMU_CONTEXT_VERSION_MASK) == 0)
46  /* It's up to date, do nothing */
47  return;
48 
49  /* It's old, we need to get new context with new version */
50  mc = ++mmu_context_cache;
51  if (!(mc & MMU_CONTEXT_ASID_MASK)) {
52  /*
53  * We have exhausted all ASIDs of this version.
54  * Flush the TLB and start new cycle.
55  */
56  flush_tlb_all();
57  /*
58  * Fix version. Note that we avoid version #0
59  * to distinguish NO_CONTEXT.
60  */
61  if (!mc)
63  }
64  mm->context = mc;
65 }
66 
67 /*
68  * Initialize the context related info for a new mm_struct
69  * instance.
70  */
71 static inline int init_new_context(struct task_struct *tsk,
72  struct mm_struct *mm)
73 {
74  mm->context = NO_CONTEXT;
75  return 0;
76 }
77 
78 /*
79  * Destroy context related info for an mm_struct that is about
80  * to be put to rest.
81  */
82 static inline void destroy_context(struct mm_struct *mm)
83 {
84  /* Do nothing */
85 }
86 
87 static inline void set_asid(unsigned long asid)
88 {
89  /* XXX: We're destroying TLBEHI[8:31] */
90  sysreg_write(TLBEHI, asid & MMU_CONTEXT_ASID_MASK);
92 }
93 
94 static inline unsigned long get_asid(void)
95 {
96  unsigned long asid;
97 
98  asid = sysreg_read(TLBEHI);
99  return asid & MMU_CONTEXT_ASID_MASK;
100 }
101 
102 static inline void activate_context(struct mm_struct *mm)
103 {
104  get_mmu_context(mm);
105  set_asid(mm->context & MMU_CONTEXT_ASID_MASK);
106 }
107 
108 static inline void switch_mm(struct mm_struct *prev,
109  struct mm_struct *next,
110  struct task_struct *tsk)
111 {
112  if (likely(prev != next)) {
113  unsigned long __pgdir = (unsigned long)next->pgd;
114 
115  sysreg_write(PTBR, __pgdir);
116  activate_context(next);
117  }
118 }
119 
120 #define deactivate_mm(tsk,mm) do { } while(0)
121 
122 #define activate_mm(prev, next) switch_mm((prev), (next), NULL)
123 
124 static inline void
125 enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
126 {
127 }
128 
129 
130 static inline void enable_mmu(void)
131 {
132  sysreg_write(MMUCR, (SYSREG_BIT(MMUCR_S)
133  | SYSREG_BIT(E)
134  | SYSREG_BIT(MMUCR_I)));
135  nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop();
136 
139 
141 }
142 
143 static inline void disable_mmu(void)
144 {
145  sysreg_write(MMUCR, SYSREG_BIT(MMUCR_S));
146 }
147 
148 #endif /* __ASM_AVR32_MMU_CONTEXT_H */