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