Commit | Line | Data |
---|---|---|
9a8fd558 CZ |
1 | /* |
2 | * include/asm-xtensa/mmu_context.h | |
3 | * | |
4 | * Switch an MMU context. | |
5 | * | |
6 | * This file is subject to the terms and conditions of the GNU General Public | |
7 | * License. See the file "COPYING" in the main directory of this archive | |
8 | * for more details. | |
9 | * | |
10 | * Copyright (C) 2001 - 2005 Tensilica Inc. | |
11 | */ | |
12 | ||
13 | #ifndef _XTENSA_MMU_CONTEXT_H | |
14 | #define _XTENSA_MMU_CONTEXT_H | |
15 | ||
e5083a63 JW |
16 | #ifndef CONFIG_MMU |
17 | #include <asm/nommu_context.h> | |
18 | #else | |
19 | ||
9a8fd558 | 20 | #include <linux/stringify.h> |
de4f6e5b | 21 | #include <linux/sched.h> |
9a8fd558 | 22 | |
4f682fbb JW |
23 | #include <variant/core.h> |
24 | ||
9a8fd558 | 25 | #include <asm/pgtable.h> |
9a8fd558 CZ |
26 | #include <asm/cacheflush.h> |
27 | #include <asm/tlbflush.h> | |
d6dd61c8 | 28 | #include <asm-generic/mm_hooks.h> |
9a8fd558 | 29 | |
9a8fd558 CZ |
30 | #if (XCHAL_HAVE_TLBS != 1) |
31 | # error "Linux must have an MMU!" | |
32 | #endif | |
33 | ||
9a8fd558 | 34 | extern unsigned long asid_cache; |
9a8fd558 CZ |
35 | |
36 | /* | |
37 | * NO_CONTEXT is the invalid ASID value that we don't ever assign to | |
173d6681 CZ |
38 | * any user or kernel context. |
39 | * | |
40 | * 0 invalid | |
41 | * 1 kernel | |
42 | * 2 reserved | |
43 | * 3 reserved | |
44 | * 4...255 available | |
9a8fd558 CZ |
45 | */ |
46 | ||
173d6681 CZ |
47 | #define NO_CONTEXT 0 |
48 | #define ASID_USER_FIRST 4 | |
49 | #define ASID_MASK ((1 << XCHAL_MMU_ASID_BITS) - 1) | |
50 | #define ASID_INSERT(x) (0x03020001 | (((x) & ASID_MASK) << 8)) | |
9a8fd558 | 51 | |
d99cf715 | 52 | static inline void set_rasid_register (unsigned long val) |
9a8fd558 | 53 | { |
bc5378fc | 54 | __asm__ __volatile__ (" wsr %0, rasid\n\t" |
9a8fd558 CZ |
55 | " isync\n" : : "a" (val)); |
56 | } | |
57 | ||
d99cf715 | 58 | static inline unsigned long get_rasid_register (void) |
9a8fd558 CZ |
59 | { |
60 | unsigned long tmp; | |
bc5378fc | 61 | __asm__ __volatile__ (" rsr %0, rasid\n\t" : "=a" (tmp)); |
9a8fd558 CZ |
62 | return tmp; |
63 | } | |
64 | ||
d99cf715 | 65 | static inline void |
173d6681 | 66 | __get_new_mmu_context(struct mm_struct *mm) |
9a8fd558 CZ |
67 | { |
68 | extern void flush_tlb_all(void); | |
173d6681 | 69 | if (! (++asid_cache & ASID_MASK) ) { |
9a8fd558 | 70 | flush_tlb_all(); /* start new asid cycle */ |
173d6681 | 71 | asid_cache += ASID_USER_FIRST; |
9a8fd558 | 72 | } |
173d6681 | 73 | mm->context = asid_cache; |
9a8fd558 CZ |
74 | } |
75 | ||
d99cf715 | 76 | static inline void |
173d6681 | 77 | __load_mmu_context(struct mm_struct *mm) |
9a8fd558 | 78 | { |
173d6681 CZ |
79 | set_rasid_register(ASID_INSERT(mm->context)); |
80 | invalidate_page_directory(); | |
9a8fd558 CZ |
81 | } |
82 | ||
9a8fd558 CZ |
83 | /* |
84 | * Initialize the context related info for a new mm_struct | |
85 | * instance. | |
86 | */ | |
87 | ||
d99cf715 | 88 | static inline int |
9a8fd558 CZ |
89 | init_new_context(struct task_struct *tsk, struct mm_struct *mm) |
90 | { | |
91 | mm->context = NO_CONTEXT; | |
92 | return 0; | |
93 | } | |
94 | ||
173d6681 CZ |
95 | /* |
96 | * After we have set current->mm to a new value, this activates | |
97 | * the context for the new mm so we see the new mappings. | |
98 | */ | |
99 | static inline void | |
100 | activate_mm(struct mm_struct *prev, struct mm_struct *next) | |
101 | { | |
102 | /* Unconditionally get a new ASID. */ | |
103 | ||
104 | __get_new_mmu_context(next); | |
105 | __load_mmu_context(next); | |
106 | } | |
107 | ||
108 | ||
d99cf715 | 109 | static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, |
9a8fd558 CZ |
110 | struct task_struct *tsk) |
111 | { | |
112 | unsigned long asid = asid_cache; | |
113 | ||
114 | /* Check if our ASID is of an older version and thus invalid */ | |
115 | ||
173d6681 CZ |
116 | if (next->context == NO_CONTEXT || ((next->context^asid) & ~ASID_MASK)) |
117 | __get_new_mmu_context(next); | |
9a8fd558 | 118 | |
173d6681 | 119 | __load_mmu_context(next); |
9a8fd558 CZ |
120 | } |
121 | ||
122 | #define deactivate_mm(tsk, mm) do { } while(0) | |
123 | ||
124 | /* | |
125 | * Destroy context related info for an mm_struct that is about | |
126 | * to be put to rest. | |
127 | */ | |
d99cf715 | 128 | static inline void destroy_context(struct mm_struct *mm) |
9a8fd558 | 129 | { |
9a8fd558 CZ |
130 | invalidate_page_directory(); |
131 | } | |
132 | ||
133 | ||
134 | static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) | |
135 | { | |
136 | /* Nothing to do. */ | |
137 | ||
138 | } | |
139 | ||
e5083a63 | 140 | #endif /* CONFIG_MMU */ |
9a8fd558 | 141 | #endif /* _XTENSA_MMU_CONTEXT_H */ |