xref: /openbmc/linux/arch/nios2/mm/mmu_context.c (revision 71995e4d)
171995e4dSLey Foon Tan /*
271995e4dSLey Foon Tan  * MMU context handling.
371995e4dSLey Foon Tan  *
471995e4dSLey Foon Tan  * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
571995e4dSLey Foon Tan  * Copyright (C) 2009 Wind River Systems Inc
671995e4dSLey Foon Tan  *   Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com
771995e4dSLey Foon Tan  *
871995e4dSLey Foon Tan  * This file is subject to the terms and conditions of the GNU General Public
971995e4dSLey Foon Tan  * License.  See the file "COPYING" in the main directory of this archive
1071995e4dSLey Foon Tan  * for more details.
1171995e4dSLey Foon Tan  */
1271995e4dSLey Foon Tan 
1371995e4dSLey Foon Tan #include <linux/mm.h>
1471995e4dSLey Foon Tan 
1571995e4dSLey Foon Tan #include <asm/cpuinfo.h>
1671995e4dSLey Foon Tan #include <asm/mmu_context.h>
1771995e4dSLey Foon Tan #include <asm/tlb.h>
1871995e4dSLey Foon Tan 
1971995e4dSLey Foon Tan /* The pids position and mask in context */
2071995e4dSLey Foon Tan #define PID_SHIFT	0
2171995e4dSLey Foon Tan #define PID_BITS	(cpuinfo.tlb_pid_num_bits)
2271995e4dSLey Foon Tan #define PID_MASK	((1UL << PID_BITS) - 1)
2371995e4dSLey Foon Tan 
2471995e4dSLey Foon Tan /* The versions position and mask in context */
2571995e4dSLey Foon Tan #define VERSION_BITS	(32 - PID_BITS)
2671995e4dSLey Foon Tan #define VERSION_SHIFT	(PID_SHIFT + PID_BITS)
2771995e4dSLey Foon Tan #define VERSION_MASK	((1UL << VERSION_BITS) - 1)
2871995e4dSLey Foon Tan 
2971995e4dSLey Foon Tan /* Return the version part of a context */
3071995e4dSLey Foon Tan #define CTX_VERSION(c)	(((c) >> VERSION_SHIFT) & VERSION_MASK)
3171995e4dSLey Foon Tan 
3271995e4dSLey Foon Tan /* Return the pid part of a context */
3371995e4dSLey Foon Tan #define CTX_PID(c)	(((c) >> PID_SHIFT) & PID_MASK)
3471995e4dSLey Foon Tan 
3571995e4dSLey Foon Tan /* Value of the first context (version 1, pid 0) */
3671995e4dSLey Foon Tan #define FIRST_CTX	((1UL << VERSION_SHIFT) | (0 << PID_SHIFT))
3771995e4dSLey Foon Tan 
3871995e4dSLey Foon Tan static mm_context_t next_mmu_context;
3971995e4dSLey Foon Tan 
4071995e4dSLey Foon Tan /*
4171995e4dSLey Foon Tan  * Initialize MMU context management stuff.
4271995e4dSLey Foon Tan  */
mmu_context_init(void)4371995e4dSLey Foon Tan void __init mmu_context_init(void)
4471995e4dSLey Foon Tan {
4571995e4dSLey Foon Tan 	/* We need to set this here because the value depends on runtime data
4671995e4dSLey Foon Tan 	 * from cpuinfo */
4771995e4dSLey Foon Tan 	next_mmu_context = FIRST_CTX;
4871995e4dSLey Foon Tan }
4971995e4dSLey Foon Tan 
5071995e4dSLey Foon Tan /*
5171995e4dSLey Foon Tan  * Set new context (pid), keep way
5271995e4dSLey Foon Tan  */
set_context(mm_context_t context)5371995e4dSLey Foon Tan static void set_context(mm_context_t context)
5471995e4dSLey Foon Tan {
5571995e4dSLey Foon Tan 	set_mmu_pid(CTX_PID(context));
5671995e4dSLey Foon Tan }
5771995e4dSLey Foon Tan 
get_new_context(void)5871995e4dSLey Foon Tan static mm_context_t get_new_context(void)
5971995e4dSLey Foon Tan {
6071995e4dSLey Foon Tan 	/* Return the next pid */
6171995e4dSLey Foon Tan 	next_mmu_context += (1UL << PID_SHIFT);
6271995e4dSLey Foon Tan 
6371995e4dSLey Foon Tan 	/* If the pid field wraps around we increase the version and
6471995e4dSLey Foon Tan 	 * flush the tlb */
6571995e4dSLey Foon Tan 	if (unlikely(CTX_PID(next_mmu_context) == 0)) {
6671995e4dSLey Foon Tan 		/* Version is incremented since the pid increment above
6771995e4dSLey Foon Tan 		 * overflows info version */
6871995e4dSLey Foon Tan 		flush_cache_all();
6971995e4dSLey Foon Tan 		flush_tlb_all();
7071995e4dSLey Foon Tan 	}
7171995e4dSLey Foon Tan 
7271995e4dSLey Foon Tan 	/* If the version wraps we start over with the first generation, we do
7371995e4dSLey Foon Tan 	 * not need to flush the tlb here since it's always done above */
7471995e4dSLey Foon Tan 	if (unlikely(CTX_VERSION(next_mmu_context) == 0))
7571995e4dSLey Foon Tan 		next_mmu_context = FIRST_CTX;
7671995e4dSLey Foon Tan 
7771995e4dSLey Foon Tan 	return next_mmu_context;
7871995e4dSLey Foon Tan }
7971995e4dSLey Foon Tan 
switch_mm(struct mm_struct * prev,struct mm_struct * next,struct task_struct * tsk)8071995e4dSLey Foon Tan void switch_mm(struct mm_struct *prev, struct mm_struct *next,
8171995e4dSLey Foon Tan 	       struct task_struct *tsk)
8271995e4dSLey Foon Tan {
8371995e4dSLey Foon Tan 	unsigned long flags;
8471995e4dSLey Foon Tan 
8571995e4dSLey Foon Tan 	local_irq_save(flags);
8671995e4dSLey Foon Tan 
8771995e4dSLey Foon Tan 	/* If the process context we are swapping in has a different context
8871995e4dSLey Foon Tan 	 * generation then we have it should get a new generation/pid */
8971995e4dSLey Foon Tan 	if (unlikely(CTX_VERSION(next->context) !=
9071995e4dSLey Foon Tan 		CTX_VERSION(next_mmu_context)))
9171995e4dSLey Foon Tan 		next->context = get_new_context();
9271995e4dSLey Foon Tan 
9371995e4dSLey Foon Tan 	/* Save the current pgd so the fast tlb handler can find it */
9471995e4dSLey Foon Tan 	pgd_current = next->pgd;
9571995e4dSLey Foon Tan 
9671995e4dSLey Foon Tan 	/* Set the current context */
9771995e4dSLey Foon Tan 	set_context(next->context);
9871995e4dSLey Foon Tan 
9971995e4dSLey Foon Tan 	local_irq_restore(flags);
10071995e4dSLey Foon Tan }
10171995e4dSLey Foon Tan 
10271995e4dSLey Foon Tan /*
10371995e4dSLey Foon Tan  * After we have set current->mm to a new value, this activates
10471995e4dSLey Foon Tan  * the context for the new mm so we see the new mappings.
10571995e4dSLey Foon Tan  */
activate_mm(struct mm_struct * prev,struct mm_struct * next)10671995e4dSLey Foon Tan void activate_mm(struct mm_struct *prev, struct mm_struct *next)
10771995e4dSLey Foon Tan {
10871995e4dSLey Foon Tan 	next->context = get_new_context();
10971995e4dSLey Foon Tan 	set_context(next->context);
11071995e4dSLey Foon Tan 	pgd_current = next->pgd;
11171995e4dSLey Foon Tan }
11271995e4dSLey Foon Tan 
get_pid_from_context(mm_context_t * context)11371995e4dSLey Foon Tan unsigned long get_pid_from_context(mm_context_t *context)
11471995e4dSLey Foon Tan {
11571995e4dSLey Foon Tan 	return CTX_PID((*context));
11671995e4dSLey Foon Tan }
117