xref: /openbmc/linux/arch/sh/include/asm/mmu_context.h (revision 589ee628)
1f15cbe6fSPaul Mundt /*
2f15cbe6fSPaul Mundt  * Copyright (C) 1999 Niibe Yutaka
3f15cbe6fSPaul Mundt  * Copyright (C) 2003 - 2007 Paul Mundt
4f15cbe6fSPaul Mundt  *
5f15cbe6fSPaul Mundt  * ASID handling idea taken from MIPS implementation.
6f15cbe6fSPaul Mundt  */
7f15cbe6fSPaul Mundt #ifndef __ASM_SH_MMU_CONTEXT_H
8f15cbe6fSPaul Mundt #define __ASM_SH_MMU_CONTEXT_H
9f15cbe6fSPaul Mundt 
10f15cbe6fSPaul Mundt #ifdef __KERNEL__
11f15cbe6fSPaul Mundt #include <cpu/mmu_context.h>
12f15cbe6fSPaul Mundt #include <asm/tlbflush.h>
137c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
14589ee628SIngo Molnar #include <linux/mm_types.h>
15589ee628SIngo Molnar 
16f15cbe6fSPaul Mundt #include <asm/io.h>
17f15cbe6fSPaul Mundt #include <asm-generic/mm_hooks.h>
18f15cbe6fSPaul Mundt 
19f15cbe6fSPaul Mundt /*
20f15cbe6fSPaul Mundt  * The MMU "context" consists of two things:
21f15cbe6fSPaul Mundt  *    (a) TLB cache version (or round, cycle whatever expression you like)
22f15cbe6fSPaul Mundt  *    (b) ASID (Address Space IDentifier)
23f15cbe6fSPaul Mundt  */
248263a67eSPaul Mundt #ifdef CONFIG_CPU_HAS_PTEAEX
258263a67eSPaul Mundt #define MMU_CONTEXT_ASID_MASK		0x0000ffff
268263a67eSPaul Mundt #else
27f15cbe6fSPaul Mundt #define MMU_CONTEXT_ASID_MASK		0x000000ff
288263a67eSPaul Mundt #endif
29f15cbe6fSPaul Mundt 
308263a67eSPaul Mundt #define MMU_CONTEXT_VERSION_MASK	(~0UL & ~MMU_CONTEXT_ASID_MASK)
318263a67eSPaul Mundt #define MMU_CONTEXT_FIRST_VERSION	(MMU_CONTEXT_ASID_MASK + 1)
328263a67eSPaul Mundt 
338263a67eSPaul Mundt /* Impossible ASID value, to differentiate from NO_CONTEXT. */
348263a67eSPaul Mundt #define MMU_NO_ASID			MMU_CONTEXT_FIRST_VERSION
358263a67eSPaul Mundt #define NO_CONTEXT			0UL
36f15cbe6fSPaul Mundt 
37f15cbe6fSPaul Mundt #define asid_cache(cpu)		(cpu_data[cpu].asid_cache)
38f15cbe6fSPaul Mundt 
39f15cbe6fSPaul Mundt #ifdef CONFIG_MMU
40f15cbe6fSPaul Mundt #define cpu_context(cpu, mm)	((mm)->context.id[cpu])
41f15cbe6fSPaul Mundt 
42f15cbe6fSPaul Mundt #define cpu_asid(cpu, mm)	\
43f15cbe6fSPaul Mundt 	(cpu_context((cpu), (mm)) & MMU_CONTEXT_ASID_MASK)
44f15cbe6fSPaul Mundt 
45f15cbe6fSPaul Mundt /*
46f15cbe6fSPaul Mundt  * Virtual Page Number mask
47f15cbe6fSPaul Mundt  */
48f15cbe6fSPaul Mundt #define MMU_VPN_MASK	0xfffff000
49f15cbe6fSPaul Mundt 
50f15cbe6fSPaul Mundt #if defined(CONFIG_SUPERH32)
51a1ce3928SDavid Howells #include <asm/mmu_context_32.h>
52f15cbe6fSPaul Mundt #else
53a1ce3928SDavid Howells #include <asm/mmu_context_64.h>
54f15cbe6fSPaul Mundt #endif
55f15cbe6fSPaul Mundt 
56f15cbe6fSPaul Mundt /*
57f15cbe6fSPaul Mundt  * Get MMU context if needed.
58f15cbe6fSPaul Mundt  */
59f15cbe6fSPaul Mundt static inline void get_mmu_context(struct mm_struct *mm, unsigned int cpu)
60f15cbe6fSPaul Mundt {
61f15cbe6fSPaul Mundt 	unsigned long asid = asid_cache(cpu);
62f15cbe6fSPaul Mundt 
63f15cbe6fSPaul Mundt 	/* Check if we have old version of context. */
64f15cbe6fSPaul Mundt 	if (((cpu_context(cpu, mm) ^ asid) & MMU_CONTEXT_VERSION_MASK) == 0)
65f15cbe6fSPaul Mundt 		/* It's up to date, do nothing */
66f15cbe6fSPaul Mundt 		return;
67f15cbe6fSPaul Mundt 
68f15cbe6fSPaul Mundt 	/* It's old, we need to get new context with new version. */
69f15cbe6fSPaul Mundt 	if (!(++asid & MMU_CONTEXT_ASID_MASK)) {
70f15cbe6fSPaul Mundt 		/*
71f15cbe6fSPaul Mundt 		 * We exhaust ASID of this version.
72f15cbe6fSPaul Mundt 		 * Flush all TLB and start new cycle.
73f15cbe6fSPaul Mundt 		 */
74711e522dSPaul Mundt 		local_flush_tlb_all();
75f15cbe6fSPaul Mundt 
76f15cbe6fSPaul Mundt #ifdef CONFIG_SUPERH64
77f15cbe6fSPaul Mundt 		/*
78f15cbe6fSPaul Mundt 		 * The SH-5 cache uses the ASIDs, requiring both the I and D
79f15cbe6fSPaul Mundt 		 * cache to be flushed when the ASID is exhausted. Weak.
80f15cbe6fSPaul Mundt 		 */
81f15cbe6fSPaul Mundt 		flush_cache_all();
82f15cbe6fSPaul Mundt #endif
83f15cbe6fSPaul Mundt 
84f15cbe6fSPaul Mundt 		/*
85f15cbe6fSPaul Mundt 		 * Fix version; Note that we avoid version #0
86aa5e5dc2SMichael Opdenacker 		 * to distinguish NO_CONTEXT.
87f15cbe6fSPaul Mundt 		 */
88f15cbe6fSPaul Mundt 		if (!asid)
89f15cbe6fSPaul Mundt 			asid = MMU_CONTEXT_FIRST_VERSION;
90f15cbe6fSPaul Mundt 	}
91f15cbe6fSPaul Mundt 
92f15cbe6fSPaul Mundt 	cpu_context(cpu, mm) = asid_cache(cpu) = asid;
93f15cbe6fSPaul Mundt }
94f15cbe6fSPaul Mundt 
95f15cbe6fSPaul Mundt /*
96f15cbe6fSPaul Mundt  * Initialize the context related info for a new mm_struct
97f15cbe6fSPaul Mundt  * instance.
98f15cbe6fSPaul Mundt  */
99f15cbe6fSPaul Mundt static inline int init_new_context(struct task_struct *tsk,
100f15cbe6fSPaul Mundt 				   struct mm_struct *mm)
101f15cbe6fSPaul Mundt {
102f15cbe6fSPaul Mundt 	int i;
103f15cbe6fSPaul Mundt 
104c8ed0010SRusty Russell 	for_each_online_cpu(i)
105f15cbe6fSPaul Mundt 		cpu_context(i, mm) = NO_CONTEXT;
106f15cbe6fSPaul Mundt 
107f15cbe6fSPaul Mundt 	return 0;
108f15cbe6fSPaul Mundt }
109f15cbe6fSPaul Mundt 
110f15cbe6fSPaul Mundt /*
111f15cbe6fSPaul Mundt  * After we have set current->mm to a new value, this activates
112f15cbe6fSPaul Mundt  * the context for the new mm so we see the new mappings.
113f15cbe6fSPaul Mundt  */
114f15cbe6fSPaul Mundt static inline void activate_context(struct mm_struct *mm, unsigned int cpu)
115f15cbe6fSPaul Mundt {
116f15cbe6fSPaul Mundt 	get_mmu_context(mm, cpu);
117f15cbe6fSPaul Mundt 	set_asid(cpu_asid(cpu, mm));
118f15cbe6fSPaul Mundt }
119f15cbe6fSPaul Mundt 
120f15cbe6fSPaul Mundt static inline void switch_mm(struct mm_struct *prev,
121f15cbe6fSPaul Mundt 			     struct mm_struct *next,
122f15cbe6fSPaul Mundt 			     struct task_struct *tsk)
123f15cbe6fSPaul Mundt {
124f15cbe6fSPaul Mundt 	unsigned int cpu = smp_processor_id();
125f15cbe6fSPaul Mundt 
126f15cbe6fSPaul Mundt 	if (likely(prev != next)) {
12774c86d67SRusty Russell 		cpumask_set_cpu(cpu, mm_cpumask(next));
128f15cbe6fSPaul Mundt 		set_TTB(next->pgd);
129f15cbe6fSPaul Mundt 		activate_context(next, cpu);
130f15cbe6fSPaul Mundt 	} else
13174c86d67SRusty Russell 		if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next)))
132f15cbe6fSPaul Mundt 			activate_context(next, cpu);
133f15cbe6fSPaul Mundt }
1347b275822SPaul Mundt 
1357b275822SPaul Mundt #define activate_mm(prev, next)		switch_mm((prev),(next),NULL)
1367b275822SPaul Mundt #define deactivate_mm(tsk,mm)		do { } while (0)
1377b275822SPaul Mundt #define enter_lazy_tlb(mm,tsk)		do { } while (0)
1387b275822SPaul Mundt 
139f15cbe6fSPaul Mundt #else
1407b275822SPaul Mundt 
141f15cbe6fSPaul Mundt #define set_asid(asid)			do { } while (0)
142f15cbe6fSPaul Mundt #define get_asid()			(0)
14335724a0aSPaul Mundt #define cpu_asid(cpu, mm)		({ (void)cpu; NO_CONTEXT; })
144f15cbe6fSPaul Mundt #define switch_and_save_asid(asid)	(0)
145f15cbe6fSPaul Mundt #define set_TTB(pgd)			do { } while (0)
146f15cbe6fSPaul Mundt #define get_TTB()			(0)
147f15cbe6fSPaul Mundt 
1487b275822SPaul Mundt #include <asm-generic/mmu_context.h>
1497b275822SPaul Mundt 
1507b275822SPaul Mundt #endif /* CONFIG_MMU */
151f15cbe6fSPaul Mundt 
152f15cbe6fSPaul Mundt #if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4)
153f15cbe6fSPaul Mundt /*
154f15cbe6fSPaul Mundt  * If this processor has an MMU, we need methods to turn it off/on ..
155f15cbe6fSPaul Mundt  * paging_init() will also have to be updated for the processor in
156f15cbe6fSPaul Mundt  * question.
157f15cbe6fSPaul Mundt  */
158f15cbe6fSPaul Mundt static inline void enable_mmu(void)
159f15cbe6fSPaul Mundt {
160f15cbe6fSPaul Mundt 	unsigned int cpu = smp_processor_id();
161f15cbe6fSPaul Mundt 
162f15cbe6fSPaul Mundt 	/* Enable MMU */
1639d56dd3bSPaul Mundt 	__raw_writel(MMU_CONTROL_INIT, MMUCR);
164f15cbe6fSPaul Mundt 	ctrl_barrier();
165f15cbe6fSPaul Mundt 
166f15cbe6fSPaul Mundt 	if (asid_cache(cpu) == NO_CONTEXT)
167f15cbe6fSPaul Mundt 		asid_cache(cpu) = MMU_CONTEXT_FIRST_VERSION;
168f15cbe6fSPaul Mundt 
169f15cbe6fSPaul Mundt 	set_asid(asid_cache(cpu) & MMU_CONTEXT_ASID_MASK);
170f15cbe6fSPaul Mundt }
171f15cbe6fSPaul Mundt 
172f15cbe6fSPaul Mundt static inline void disable_mmu(void)
173f15cbe6fSPaul Mundt {
174f15cbe6fSPaul Mundt 	unsigned long cr;
175f15cbe6fSPaul Mundt 
1769d56dd3bSPaul Mundt 	cr = __raw_readl(MMUCR);
177f15cbe6fSPaul Mundt 	cr &= ~MMU_CONTROL_INIT;
1789d56dd3bSPaul Mundt 	__raw_writel(cr, MMUCR);
179f15cbe6fSPaul Mundt 
180f15cbe6fSPaul Mundt 	ctrl_barrier();
181f15cbe6fSPaul Mundt }
182f15cbe6fSPaul Mundt #else
183f15cbe6fSPaul Mundt /*
184f15cbe6fSPaul Mundt  * MMU control handlers for processors lacking memory
185f15cbe6fSPaul Mundt  * management hardware.
186f15cbe6fSPaul Mundt  */
187f15cbe6fSPaul Mundt #define enable_mmu()	do { } while (0)
188f15cbe6fSPaul Mundt #define disable_mmu()	do { } while (0)
189f15cbe6fSPaul Mundt #endif
190f15cbe6fSPaul Mundt 
191f15cbe6fSPaul Mundt #endif /* __KERNEL__ */
192f15cbe6fSPaul Mundt #endif /* __ASM_SH_MMU_CONTEXT_H */
193