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