xref: /openbmc/linux/arch/sh/include/asm/mmu_context.h (revision c350f8c7)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
2f15cbe6fSPaul Mundt /*
3f15cbe6fSPaul Mundt  * Copyright (C) 1999 Niibe Yutaka
4f15cbe6fSPaul Mundt  * Copyright (C) 2003 - 2007 Paul Mundt
5f15cbe6fSPaul Mundt  *
6f15cbe6fSPaul Mundt  * ASID handling idea taken from MIPS implementation.
7f15cbe6fSPaul Mundt  */
8f15cbe6fSPaul Mundt #ifndef __ASM_SH_MMU_CONTEXT_H
9f15cbe6fSPaul Mundt #define __ASM_SH_MMU_CONTEXT_H
10f15cbe6fSPaul Mundt 
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 
50a1ce3928SDavid Howells #include <asm/mmu_context_32.h>
51f15cbe6fSPaul Mundt 
52f15cbe6fSPaul Mundt /*
53f15cbe6fSPaul Mundt  * Get MMU context if needed.
54f15cbe6fSPaul Mundt  */
get_mmu_context(struct mm_struct * mm,unsigned int cpu)55f15cbe6fSPaul Mundt static inline void get_mmu_context(struct mm_struct *mm, unsigned int cpu)
56f15cbe6fSPaul Mundt {
57f15cbe6fSPaul Mundt 	unsigned long asid = asid_cache(cpu);
58f15cbe6fSPaul Mundt 
59f15cbe6fSPaul Mundt 	/* Check if we have old version of context. */
60f15cbe6fSPaul Mundt 	if (((cpu_context(cpu, mm) ^ asid) & MMU_CONTEXT_VERSION_MASK) == 0)
61f15cbe6fSPaul Mundt 		/* It's up to date, do nothing */
62f15cbe6fSPaul Mundt 		return;
63f15cbe6fSPaul Mundt 
64f15cbe6fSPaul Mundt 	/* It's old, we need to get new context with new version. */
65f15cbe6fSPaul Mundt 	if (!(++asid & MMU_CONTEXT_ASID_MASK)) {
66f15cbe6fSPaul Mundt 		/*
67f15cbe6fSPaul Mundt 		 * We exhaust ASID of this version.
68f15cbe6fSPaul Mundt 		 * Flush all TLB and start new cycle.
69f15cbe6fSPaul Mundt 		 */
70711e522dSPaul Mundt 		local_flush_tlb_all();
71f15cbe6fSPaul Mundt 
72f15cbe6fSPaul Mundt 		/*
73f15cbe6fSPaul Mundt 		 * Fix version; Note that we avoid version #0
74aa5e5dc2SMichael Opdenacker 		 * to distinguish NO_CONTEXT.
75f15cbe6fSPaul Mundt 		 */
76f15cbe6fSPaul Mundt 		if (!asid)
77f15cbe6fSPaul Mundt 			asid = MMU_CONTEXT_FIRST_VERSION;
78f15cbe6fSPaul Mundt 	}
79f15cbe6fSPaul Mundt 
80f15cbe6fSPaul Mundt 	cpu_context(cpu, mm) = asid_cache(cpu) = asid;
81f15cbe6fSPaul Mundt }
82f15cbe6fSPaul Mundt 
83f15cbe6fSPaul Mundt /*
84f15cbe6fSPaul Mundt  * Initialize the context related info for a new mm_struct
85f15cbe6fSPaul Mundt  * instance.
86f15cbe6fSPaul Mundt  */
87*c350f8c7SNicholas Piggin #define init_new_context init_new_context
init_new_context(struct task_struct * tsk,struct mm_struct * mm)88f15cbe6fSPaul Mundt static inline int init_new_context(struct task_struct *tsk,
89f15cbe6fSPaul Mundt 				   struct mm_struct *mm)
90f15cbe6fSPaul Mundt {
91f15cbe6fSPaul Mundt 	int i;
92f15cbe6fSPaul Mundt 
93c8ed0010SRusty Russell 	for_each_online_cpu(i)
94f15cbe6fSPaul Mundt 		cpu_context(i, mm) = NO_CONTEXT;
95f15cbe6fSPaul Mundt 
96f15cbe6fSPaul Mundt 	return 0;
97f15cbe6fSPaul Mundt }
98f15cbe6fSPaul Mundt 
99f15cbe6fSPaul Mundt /*
100f15cbe6fSPaul Mundt  * After we have set current->mm to a new value, this activates
101f15cbe6fSPaul Mundt  * the context for the new mm so we see the new mappings.
102f15cbe6fSPaul Mundt  */
activate_context(struct mm_struct * mm,unsigned int cpu)103f15cbe6fSPaul Mundt static inline void activate_context(struct mm_struct *mm, unsigned int cpu)
104f15cbe6fSPaul Mundt {
105f15cbe6fSPaul Mundt 	get_mmu_context(mm, cpu);
106f15cbe6fSPaul Mundt 	set_asid(cpu_asid(cpu, mm));
107f15cbe6fSPaul Mundt }
108f15cbe6fSPaul Mundt 
switch_mm(struct mm_struct * prev,struct mm_struct * next,struct task_struct * tsk)109f15cbe6fSPaul Mundt static inline void switch_mm(struct mm_struct *prev,
110f15cbe6fSPaul Mundt 			     struct mm_struct *next,
111f15cbe6fSPaul Mundt 			     struct task_struct *tsk)
112f15cbe6fSPaul Mundt {
113f15cbe6fSPaul Mundt 	unsigned int cpu = smp_processor_id();
114f15cbe6fSPaul Mundt 
115f15cbe6fSPaul Mundt 	if (likely(prev != next)) {
11674c86d67SRusty Russell 		cpumask_set_cpu(cpu, mm_cpumask(next));
117f15cbe6fSPaul Mundt 		set_TTB(next->pgd);
118f15cbe6fSPaul Mundt 		activate_context(next, cpu);
119f15cbe6fSPaul Mundt 	} else
12074c86d67SRusty Russell 		if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next)))
121f15cbe6fSPaul Mundt 			activate_context(next, cpu);
122f15cbe6fSPaul Mundt }
1237b275822SPaul Mundt 
124*c350f8c7SNicholas Piggin #include <asm-generic/mmu_context.h>
1257b275822SPaul Mundt 
126f15cbe6fSPaul Mundt #else
1277b275822SPaul Mundt 
128f15cbe6fSPaul Mundt #define set_asid(asid)			do { } while (0)
129f15cbe6fSPaul Mundt #define get_asid()			(0)
13035724a0aSPaul Mundt #define cpu_asid(cpu, mm)		({ (void)cpu; NO_CONTEXT; })
131f15cbe6fSPaul Mundt #define switch_and_save_asid(asid)	(0)
132f15cbe6fSPaul Mundt #define set_TTB(pgd)			do { } while (0)
133f15cbe6fSPaul Mundt #define get_TTB()			(0)
134f15cbe6fSPaul Mundt 
13594f89922SNicholas Piggin #include <asm-generic/nommu_context.h>
1367b275822SPaul Mundt 
1377b275822SPaul Mundt #endif /* CONFIG_MMU */
138f15cbe6fSPaul Mundt 
139f15cbe6fSPaul Mundt #if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4)
140f15cbe6fSPaul Mundt /*
141f15cbe6fSPaul Mundt  * If this processor has an MMU, we need methods to turn it off/on ..
142f15cbe6fSPaul Mundt  * paging_init() will also have to be updated for the processor in
143f15cbe6fSPaul Mundt  * question.
144f15cbe6fSPaul Mundt  */
enable_mmu(void)145f15cbe6fSPaul Mundt static inline void enable_mmu(void)
146f15cbe6fSPaul Mundt {
147f15cbe6fSPaul Mundt 	unsigned int cpu = smp_processor_id();
148f15cbe6fSPaul Mundt 
149f15cbe6fSPaul Mundt 	/* Enable MMU */
1509d56dd3bSPaul Mundt 	__raw_writel(MMU_CONTROL_INIT, MMUCR);
151f15cbe6fSPaul Mundt 	ctrl_barrier();
152f15cbe6fSPaul Mundt 
153f15cbe6fSPaul Mundt 	if (asid_cache(cpu) == NO_CONTEXT)
154f15cbe6fSPaul Mundt 		asid_cache(cpu) = MMU_CONTEXT_FIRST_VERSION;
155f15cbe6fSPaul Mundt 
156f15cbe6fSPaul Mundt 	set_asid(asid_cache(cpu) & MMU_CONTEXT_ASID_MASK);
157f15cbe6fSPaul Mundt }
158f15cbe6fSPaul Mundt 
disable_mmu(void)159f15cbe6fSPaul Mundt static inline void disable_mmu(void)
160f15cbe6fSPaul Mundt {
161f15cbe6fSPaul Mundt 	unsigned long cr;
162f15cbe6fSPaul Mundt 
1639d56dd3bSPaul Mundt 	cr = __raw_readl(MMUCR);
164f15cbe6fSPaul Mundt 	cr &= ~MMU_CONTROL_INIT;
1659d56dd3bSPaul Mundt 	__raw_writel(cr, MMUCR);
166f15cbe6fSPaul Mundt 
167f15cbe6fSPaul Mundt 	ctrl_barrier();
168f15cbe6fSPaul Mundt }
169f15cbe6fSPaul Mundt #else
170f15cbe6fSPaul Mundt /*
171f15cbe6fSPaul Mundt  * MMU control handlers for processors lacking memory
172f15cbe6fSPaul Mundt  * management hardware.
173f15cbe6fSPaul Mundt  */
174f15cbe6fSPaul Mundt #define enable_mmu()	do { } while (0)
175f15cbe6fSPaul Mundt #define disable_mmu()	do { } while (0)
176f15cbe6fSPaul Mundt #endif
177f15cbe6fSPaul Mundt 
178f15cbe6fSPaul Mundt #endif /* __ASM_SH_MMU_CONTEXT_H */
179