mmu_context.h 4.4 KB
Newer Older
L
Linus Torvalds 已提交
1 2
/*
 * Copyright (C) 1999 Niibe Yutaka
3
 * Copyright (C) 2003 - 2007 Paul Mundt
L
Linus Torvalds 已提交
4 5 6 7 8 9
 *
 * ASID handling idea taken from MIPS implementation.
 */
#ifndef __ASM_SH_MMU_CONTEXT_H
#define __ASM_SH_MMU_CONTEXT_H

10
#ifdef __KERNEL__
P
Paul Mundt 已提交
11
#include <cpu/mmu_context.h>
L
Linus Torvalds 已提交
12 13 14
#include <asm/tlbflush.h>
#include <asm/uaccess.h>
#include <asm/io.h>
15
#include <asm-generic/mm_hooks.h>
L
Linus Torvalds 已提交
16 17 18 19 20 21

/*
 * The MMU "context" consists of two things:
 *    (a) TLB cache version (or round, cycle whatever expression you like)
 *    (b) ASID (Address Space IDentifier)
 */
22 23 24
#ifdef CONFIG_CPU_HAS_PTEAEX
#define MMU_CONTEXT_ASID_MASK		0x0000ffff
#else
L
Linus Torvalds 已提交
25
#define MMU_CONTEXT_ASID_MASK		0x000000ff
26
#endif
L
Linus Torvalds 已提交
27

28 29 30 31 32 33
#define MMU_CONTEXT_VERSION_MASK	(~0UL & ~MMU_CONTEXT_ASID_MASK)
#define MMU_CONTEXT_FIRST_VERSION	(MMU_CONTEXT_ASID_MASK + 1)

/* Impossible ASID value, to differentiate from NO_CONTEXT. */
#define MMU_NO_ASID			MMU_CONTEXT_FIRST_VERSION
#define NO_CONTEXT			0UL
L
Linus Torvalds 已提交
34

P
Paul Mundt 已提交
35
#define asid_cache(cpu)		(cpu_data[cpu].asid_cache)
36 37

#ifdef CONFIG_MMU
38 39 40 41
#define cpu_context(cpu, mm)	((mm)->context.id[cpu])

#define cpu_asid(cpu, mm)	\
	(cpu_context((cpu), (mm)) & MMU_CONTEXT_ASID_MASK)
P
Paul Mundt 已提交
42

L
Linus Torvalds 已提交
43 44 45 46 47
/*
 * Virtual Page Number mask
 */
#define MMU_VPN_MASK	0xfffff000

48 49 50 51 52 53
#if defined(CONFIG_SUPERH32)
#include "mmu_context_32.h"
#else
#include "mmu_context_64.h"
#endif

L
Linus Torvalds 已提交
54 55 56
/*
 * Get MMU context if needed.
 */
P
Paul Mundt 已提交
57
static inline void get_mmu_context(struct mm_struct *mm, unsigned int cpu)
L
Linus Torvalds 已提交
58
{
P
Paul Mundt 已提交
59
	unsigned long asid = asid_cache(cpu);
L
Linus Torvalds 已提交
60 61

	/* Check if we have old version of context. */
P
Paul Mundt 已提交
62
	if (((cpu_context(cpu, mm) ^ asid) & MMU_CONTEXT_VERSION_MASK) == 0)
L
Linus Torvalds 已提交
63 64 65 66
		/* It's up to date, do nothing */
		return;

	/* It's old, we need to get new context with new version. */
P
Paul Mundt 已提交
67
	if (!(++asid & MMU_CONTEXT_ASID_MASK)) {
L
Linus Torvalds 已提交
68 69 70 71 72
		/*
		 * We exhaust ASID of this version.
		 * Flush all TLB and start new cycle.
		 */
		flush_tlb_all();
73

74 75 76 77 78 79 80 81
#ifdef CONFIG_SUPERH64
		/*
		 * The SH-5 cache uses the ASIDs, requiring both the I and D
		 * cache to be flushed when the ASID is exhausted. Weak.
		 */
		flush_cache_all();
#endif

L
Linus Torvalds 已提交
82 83 84 85
		/*
		 * Fix version; Note that we avoid version #0
		 * to distingush NO_CONTEXT.
		 */
P
Paul Mundt 已提交
86 87
		if (!asid)
			asid = MMU_CONTEXT_FIRST_VERSION;
L
Linus Torvalds 已提交
88
	}
P
Paul Mundt 已提交
89 90

	cpu_context(cpu, mm) = asid_cache(cpu) = asid;
L
Linus Torvalds 已提交
91 92 93 94 95 96
}

/*
 * Initialize the context related info for a new mm_struct
 * instance.
 */
97
static inline int init_new_context(struct task_struct *tsk,
P
Paul Mundt 已提交
98
				   struct mm_struct *mm)
L
Linus Torvalds 已提交
99
{
P
Paul Mundt 已提交
100 101 102 103 104
	int i;

	for (i = 0; i < num_online_cpus(); i++)
		cpu_context(i, mm) = NO_CONTEXT;

L
Linus Torvalds 已提交
105 106 107 108 109 110 111
	return 0;
}

/*
 * After we have set current->mm to a new value, this activates
 * the context for the new mm so we see the new mappings.
 */
P
Paul Mundt 已提交
112
static inline void activate_context(struct mm_struct *mm, unsigned int cpu)
L
Linus Torvalds 已提交
113
{
P
Paul Mundt 已提交
114 115
	get_mmu_context(mm, cpu);
	set_asid(cpu_asid(cpu, mm));
L
Linus Torvalds 已提交
116 117
}

118 119 120 121
static inline void switch_mm(struct mm_struct *prev,
			     struct mm_struct *next,
			     struct task_struct *tsk)
{
P
Paul Mundt 已提交
122 123
	unsigned int cpu = smp_processor_id();

124
	if (likely(prev != next)) {
125
		cpumask_set_cpu(cpu, mm_cpumask(next));
126
		set_TTB(next->pgd);
P
Paul Mundt 已提交
127 128
		activate_context(next, cpu);
	} else
129
		if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next)))
P
Paul Mundt 已提交
130
			activate_context(next, cpu);
L
Linus Torvalds 已提交
131
}
132 133 134 135 136

#define activate_mm(prev, next)		switch_mm((prev),(next),NULL)
#define deactivate_mm(tsk,mm)		do { } while (0)
#define enter_lazy_tlb(mm,tsk)		do { } while (0)

137
#else
138

L
Linus Torvalds 已提交
139 140
#define set_asid(asid)			do { } while (0)
#define get_asid()			(0)
141
#define cpu_asid(cpu, mm)		({ (void)cpu; NO_CONTEXT; })
P
Paul Mundt 已提交
142
#define switch_and_save_asid(asid)	(0)
143 144
#define set_TTB(pgd)			do { } while (0)
#define get_TTB()			(0)
145

146 147 148
#include <asm-generic/mmu_context.h>

#endif /* CONFIG_MMU */
L
Linus Torvalds 已提交
149 150 151 152 153 154 155 156 157

#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4)
/*
 * If this processor has an MMU, we need methods to turn it off/on ..
 * paging_init() will also have to be updated for the processor in
 * question.
 */
static inline void enable_mmu(void)
{
P
Paul Mundt 已提交
158 159
	unsigned int cpu = smp_processor_id();

L
Linus Torvalds 已提交
160 161
	/* Enable MMU */
	ctrl_outl(MMU_CONTROL_INIT, MMUCR);
P
Paul Mundt 已提交
162
	ctrl_barrier();
L
Linus Torvalds 已提交
163

P
Paul Mundt 已提交
164 165
	if (asid_cache(cpu) == NO_CONTEXT)
		asid_cache(cpu) = MMU_CONTEXT_FIRST_VERSION;
L
Linus Torvalds 已提交
166

P
Paul Mundt 已提交
167
	set_asid(asid_cache(cpu) & MMU_CONTEXT_ASID_MASK);
L
Linus Torvalds 已提交
168 169 170 171 172 173 174 175 176
}

static inline void disable_mmu(void)
{
	unsigned long cr;

	cr = ctrl_inl(MMUCR);
	cr &= ~MMU_CONTROL_INIT;
	ctrl_outl(cr, MMUCR);
P
Paul Mundt 已提交
177 178

	ctrl_barrier();
L
Linus Torvalds 已提交
179 180 181 182 183 184
}
#else
/*
 * MMU control handlers for processors lacking memory
 * management hardware.
 */
185 186
#define enable_mmu()	do { } while (0)
#define disable_mmu()	do { } while (0)
L
Linus Torvalds 已提交
187 188 189 190
#endif

#endif /* __KERNEL__ */
#endif /* __ASM_SH_MMU_CONTEXT_H */