patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / include / asm-ppc64 / mmu_context.h
1 #ifndef __PPC64_MMU_CONTEXT_H
2 #define __PPC64_MMU_CONTEXT_H
3
4 #include <linux/config.h>
5 #include <linux/spinlock.h>     
6 #include <linux/kernel.h>       
7 #include <linux/mm.h>   
8 #include <asm/mmu.h>    
9 #include <asm/ppcdebug.h>       
10 #include <asm/cputable.h>
11
12 /*
13  * Copyright (C) 2001 PPC 64 Team, IBM Corp
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version
18  * 2 of the License, or (at your option) any later version.
19  */
20
21 /*
22  * Every architecture must define this function. It's the fastest
23  * way of searching a 140-bit bitmap where the first 100 bits are
24  * unlikely to be set. It's guaranteed that at least one of the 140
25  * bits is cleared.
26  */
27 static inline int sched_find_first_bit(unsigned long *b)
28 {
29         if (unlikely(b[0]))
30                 return __ffs(b[0]);
31         if (unlikely(b[1]))
32                 return __ffs(b[1]) + 64;
33         return __ffs(b[2]) + 128;
34 }
35
36 #define NO_CONTEXT              0
37 #define FIRST_USER_CONTEXT      0x10    /* First 16 reserved for kernel */
38 #define LAST_USER_CONTEXT       0x8000  /* Same as PID_MAX for now... */
39 #define NUM_USER_CONTEXT        (LAST_USER_CONTEXT-FIRST_USER_CONTEXT)
40
41 /* Choose whether we want to implement our context
42  * number allocator as a LIFO or FIFO queue.
43  */
44 #if 1
45 #define MMU_CONTEXT_LIFO
46 #else
47 #define MMU_CONTEXT_FIFO
48 #endif
49
50 struct mmu_context_queue_t {
51         spinlock_t lock;
52         long head;
53         long tail;
54         long size;
55         mm_context_id_t elements[LAST_USER_CONTEXT];
56 };
57
58 extern struct mmu_context_queue_t mmu_context_queue;
59
60 static inline void
61 enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
62 {
63 }
64
65 /*
66  * The context number queue has underflowed.
67  * Meaning: we tried to push a context number that was freed
68  * back onto the context queue and the queue was already full.
69  */
70 static inline void
71 mmu_context_underflow(void)
72 {
73         printk(KERN_DEBUG "mmu_context_underflow\n");
74         panic("mmu_context_underflow");
75 }
76
77 /*
78  * Set up the context for a new address space.
79  */
80 static inline int
81 init_new_context(struct task_struct *tsk, struct mm_struct *mm)
82 {
83         long head;
84         unsigned long flags;
85         /* This does the right thing across a fork (I hope) */
86
87         spin_lock_irqsave(&mmu_context_queue.lock, flags);
88
89         if (mmu_context_queue.size <= 0) {
90                 spin_unlock_irqrestore(&mmu_context_queue.lock, flags);
91                 return -ENOMEM;
92         }
93
94         head = mmu_context_queue.head;
95         mm->context.id = mmu_context_queue.elements[head];
96
97         head = (head < LAST_USER_CONTEXT-1) ? head+1 : 0;
98         mmu_context_queue.head = head;
99         mmu_context_queue.size--;
100
101         spin_unlock_irqrestore(&mmu_context_queue.lock, flags);
102
103         return 0;
104 }
105
106 /*
107  * We're finished using the context for an address space.
108  */
109 static inline void
110 destroy_context(struct mm_struct *mm)
111 {
112         long index;
113         unsigned long flags;
114
115         spin_lock_irqsave(&mmu_context_queue.lock, flags);
116
117         if (mmu_context_queue.size >= NUM_USER_CONTEXT) {
118                 spin_unlock_irqrestore(&mmu_context_queue.lock, flags);
119                 mmu_context_underflow();
120         }
121
122 #ifdef MMU_CONTEXT_LIFO
123         index = mmu_context_queue.head;
124         index = (index > 0) ? index-1 : LAST_USER_CONTEXT-1;
125         mmu_context_queue.head = index;
126 #else
127         index = mmu_context_queue.tail;
128         index = (index < LAST_USER_CONTEXT-1) ? index+1 : 0;
129         mmu_context_queue.tail = index;
130 #endif
131
132         mmu_context_queue.size++;
133         mmu_context_queue.elements[index] = mm->context.id;
134
135         spin_unlock_irqrestore(&mmu_context_queue.lock, flags);
136 }
137
138 extern void flush_stab(struct task_struct *tsk, struct mm_struct *mm);
139 extern void flush_slb(struct task_struct *tsk, struct mm_struct *mm);
140
141 /*
142  * switch_mm is the entry point called from the architecture independent
143  * code in kernel/sched.c
144  */
145 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
146                              struct task_struct *tsk)
147 {
148 #ifdef CONFIG_ALTIVEC
149         asm volatile (
150  BEGIN_FTR_SECTION
151         "dssall;\n"
152  END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
153          : : );
154 #endif /* CONFIG_ALTIVEC */
155
156         if (!cpu_isset(smp_processor_id(), next->cpu_vm_mask))
157                 cpu_set(smp_processor_id(), next->cpu_vm_mask);
158
159         /* No need to flush userspace segments if the mm doesnt change */
160         if (prev == next)
161                 return;
162
163         if (cur_cpu_spec->cpu_features & CPU_FTR_SLB)
164                 flush_slb(tsk, next);
165         else
166                 flush_stab(tsk, next);
167 }
168
169 #define deactivate_mm(tsk,mm)   do { } while (0)
170
171 /*
172  * After we have set current->mm to a new value, this activates
173  * the context for the new mm so we see the new mappings.
174  */
175 static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
176 {
177         unsigned long flags;
178
179         local_irq_save(flags);
180         switch_mm(prev, next, current);
181         local_irq_restore(flags);
182 }
183
184 #define VSID_RANDOMIZER 42470972311UL
185 #define VSID_MASK       0xfffffffffUL
186
187
188 /* This is only valid for kernel (including vmalloc, imalloc and bolted) EA's
189  */
190 static inline unsigned long
191 get_kernel_vsid( unsigned long ea )
192 {
193         unsigned long ordinal, vsid;
194         
195         ordinal = (((ea >> 28) & 0x1fff) * LAST_USER_CONTEXT) | (ea >> 60);
196         vsid = (ordinal * VSID_RANDOMIZER) & VSID_MASK;
197
198 #ifdef HTABSTRESS
199         /* For debug, this path creates a very poor vsid distribuition.
200          * A user program can access virtual addresses in the form
201          * 0x0yyyyxxxx000 where yyyy = xxxx to cause multiple mappings
202          * to hash to the same page table group.
203          */
204         ordinal = ((ea >> 28) & 0x1fff) | (ea >> 44);
205         vsid = ordinal & VSID_MASK;
206 #endif /* HTABSTRESS */
207
208         return vsid;
209
210
211 /* This is only valid for user EA's (user EA's do not exceed 2^41 (EADDR_SIZE))
212  */
213 static inline unsigned long
214 get_vsid( unsigned long context, unsigned long ea )
215 {
216         unsigned long ordinal, vsid;
217
218         ordinal = (((ea >> 28) & 0x1fff) * LAST_USER_CONTEXT) | context;
219         vsid = (ordinal * VSID_RANDOMIZER) & VSID_MASK;
220
221 #ifdef HTABSTRESS
222         /* See comment above. */
223         ordinal = ((ea >> 28) & 0x1fff) | (context << 16);
224         vsid = ordinal & VSID_MASK;
225 #endif /* HTABSTRESS */
226
227         return vsid;
228 }
229
230 #endif /* __PPC64_MMU_CONTEXT_H */