Merge branch 'fix/hda' into for-linus
[pandora-kernel.git] / arch / blackfin / include / asm / mmu_context.h
1 /*
2  * Copyright 2004-2009 Analog Devices Inc.
3  *
4  * Licensed under the GPL-2 or later.
5  */
6
7 #ifndef __BLACKFIN_MMU_CONTEXT_H__
8 #define __BLACKFIN_MMU_CONTEXT_H__
9
10 #include <linux/gfp.h>
11 #include <linux/sched.h>
12 #include <asm/setup.h>
13 #include <asm/page.h>
14 #include <asm/pgalloc.h>
15 #include <asm/cplbinit.h>
16
17 /* Note: L1 stacks are CPU-private things, so we bluntly disable this
18    feature in SMP mode, and use the per-CPU scratch SRAM bank only to
19    store the PDA instead. */
20
21 extern void *current_l1_stack_save;
22 extern int nr_l1stack_tasks;
23 extern void *l1_stack_base;
24 extern unsigned long l1_stack_len;
25
26 extern int l1sram_free(const void*);
27 extern void *l1sram_alloc_max(void*);
28
29 static inline void free_l1stack(void)
30 {
31         nr_l1stack_tasks--;
32         if (nr_l1stack_tasks == 0)
33                 l1sram_free(l1_stack_base);
34 }
35
36 static inline unsigned long
37 alloc_l1stack(unsigned long length, unsigned long *stack_base)
38 {
39         if (nr_l1stack_tasks == 0) {
40                 l1_stack_base = l1sram_alloc_max(&l1_stack_len);
41                 if (!l1_stack_base)
42                         return 0;
43         }
44
45         if (l1_stack_len < length) {
46                 if (nr_l1stack_tasks == 0)
47                         l1sram_free(l1_stack_base);
48                 return 0;
49         }
50         *stack_base = (unsigned long)l1_stack_base;
51         nr_l1stack_tasks++;
52         return l1_stack_len;
53 }
54
55 static inline int
56 activate_l1stack(struct mm_struct *mm, unsigned long sp_base)
57 {
58         if (current_l1_stack_save)
59                 memcpy(current_l1_stack_save, l1_stack_base, l1_stack_len);
60         mm->context.l1_stack_save = current_l1_stack_save = (void*)sp_base;
61         memcpy(l1_stack_base, current_l1_stack_save, l1_stack_len);
62         return 1;
63 }
64
65 #define deactivate_mm(tsk,mm)   do { } while (0)
66
67 #define activate_mm(prev, next) switch_mm(prev, next, NULL)
68
69 static inline void __switch_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm,
70                                struct task_struct *tsk)
71 {
72 #ifdef CONFIG_MPU
73         unsigned int cpu = smp_processor_id();
74 #endif
75         if (prev_mm == next_mm)
76                 return;
77 #ifdef CONFIG_MPU
78         if (prev_mm->context.page_rwx_mask == current_rwx_mask[cpu]) {
79                 flush_switched_cplbs(cpu);
80                 set_mask_dcplbs(next_mm->context.page_rwx_mask, cpu);
81         }
82 #endif
83
84 #ifdef CONFIG_APP_STACK_L1
85         /* L1 stack switching.  */
86         if (!next_mm->context.l1_stack_save)
87                 return;
88         if (next_mm->context.l1_stack_save == current_l1_stack_save)
89                 return;
90         if (current_l1_stack_save) {
91                 memcpy(current_l1_stack_save, l1_stack_base, l1_stack_len);
92         }
93         current_l1_stack_save = next_mm->context.l1_stack_save;
94         memcpy(l1_stack_base, current_l1_stack_save, l1_stack_len);
95 #endif
96 }
97
98 #ifdef CONFIG_IPIPE
99 #define lock_mm_switch(flags)   local_irq_save_hw_cond(flags)
100 #define unlock_mm_switch(flags) local_irq_restore_hw_cond(flags)
101 #else
102 #define lock_mm_switch(flags)   do { (void)(flags); } while (0)
103 #define unlock_mm_switch(flags) do { (void)(flags); } while (0)
104 #endif /* CONFIG_IPIPE */
105
106 #ifdef CONFIG_MPU
107 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
108                              struct task_struct *tsk)
109 {
110         unsigned long flags;
111         lock_mm_switch(flags);
112         __switch_mm(prev, next, tsk);
113         unlock_mm_switch(flags);
114 }
115
116 static inline void protect_page(struct mm_struct *mm, unsigned long addr,
117                                 unsigned long flags)
118 {
119         unsigned long *mask = mm->context.page_rwx_mask;
120         unsigned long page = addr >> 12;
121         unsigned long idx = page >> 5;
122         unsigned long bit = 1 << (page & 31);
123
124         if (flags & VM_READ)
125                 mask[idx] |= bit;
126         else
127                 mask[idx] &= ~bit;
128         mask += page_mask_nelts;
129         if (flags & VM_WRITE)
130                 mask[idx] |= bit;
131         else
132                 mask[idx] &= ~bit;
133         mask += page_mask_nelts;
134         if (flags & VM_EXEC)
135                 mask[idx] |= bit;
136         else
137                 mask[idx] &= ~bit;
138 }
139
140 static inline void update_protections(struct mm_struct *mm)
141 {
142         unsigned int cpu = smp_processor_id();
143         if (mm->context.page_rwx_mask == current_rwx_mask[cpu]) {
144                 flush_switched_cplbs(cpu);
145                 set_mask_dcplbs(mm->context.page_rwx_mask, cpu);
146         }
147 }
148 #else /* !CONFIG_MPU */
149 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
150                              struct task_struct *tsk)
151 {
152         __switch_mm(prev, next, tsk);
153 }
154 #endif
155
156 static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
157 {
158 }
159
160 /* Called when creating a new context during fork() or execve().  */
161 static inline int
162 init_new_context(struct task_struct *tsk, struct mm_struct *mm)
163 {
164 #ifdef CONFIG_MPU
165         unsigned long p = __get_free_pages(GFP_KERNEL, page_mask_order);
166         mm->context.page_rwx_mask = (unsigned long *)p;
167         memset(mm->context.page_rwx_mask, 0,
168                page_mask_nelts * 3 * sizeof(long));
169 #endif
170         return 0;
171 }
172
173 static inline void destroy_context(struct mm_struct *mm)
174 {
175         struct sram_list_struct *tmp;
176 #ifdef CONFIG_MPU
177         unsigned int cpu = smp_processor_id();
178 #endif
179
180 #ifdef CONFIG_APP_STACK_L1
181         if (current_l1_stack_save == mm->context.l1_stack_save)
182                 current_l1_stack_save = 0;
183         if (mm->context.l1_stack_save)
184                 free_l1stack();
185 #endif
186
187         while ((tmp = mm->context.sram_list)) {
188                 mm->context.sram_list = tmp->next;
189                 sram_free(tmp->addr);
190                 kfree(tmp);
191         }
192 #ifdef CONFIG_MPU
193         if (current_rwx_mask[cpu] == mm->context.page_rwx_mask)
194                 current_rwx_mask[cpu] = NULL;
195         free_pages((unsigned long)mm->context.page_rwx_mask, page_mask_order);
196 #endif
197 }
198
199 #define ipipe_mm_switch_protect(flags)          \
200         local_irq_save_hw_cond(flags)
201
202 #define ipipe_mm_switch_unprotect(flags)        \
203         local_irq_restore_hw_cond(flags)
204
205 #endif