1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include <linux/init.h>
27#include <linux/linkage.h>
28#include <linux/kernel.h>
29#include <linux/mm.h>
30#include <linux/module.h>
31#include <linux/sched.h>
32#include <linux/fs.h>
33
34#include <asm/mmu_context.h>
35
36
37
38
39
40
41
42static void flush_data_cache_page(unsigned long addr)
43{
44 unsigned int i;
45 for (i = 0; i < (PAGE_SIZE / L1_CACHE_BYTES); i += L1_CACHE_BYTES) {
46 __asm__ __volatile__(
47 "cache 0x0e, [%0, 0]\n"
48 "cache 0x1a, [%0, 0]\n"
49 "nop\n"
50 : : "r" (addr));
51 addr += L1_CACHE_BYTES;
52 }
53}
54
55void flush_dcache_page(struct page *page)
56{
57 struct address_space *mapping = page_mapping(page);
58 unsigned long addr;
59
60 if (PageHighMem(page))
61 return;
62 if (mapping && !mapping_mapped(mapping)) {
63 set_bit(PG_dcache_dirty, &(page)->flags);
64 return;
65 }
66
67
68
69
70
71
72 addr = (unsigned long) page_address(page);
73 flush_data_cache_page(addr);
74}
75
76
77void __update_cache(struct vm_area_struct *vma, unsigned long address,
78 pte_t pte)
79{
80 struct page *page;
81 unsigned long pfn, addr;
82 int exec = (vma->vm_flags & VM_EXEC);
83
84 pfn = pte_pfn(pte);
85 if (unlikely(!pfn_valid(pfn)))
86 return;
87 page = pfn_to_page(pfn);
88 if (page_mapping(page) && test_bit(PG_dcache_dirty, &(page)->flags)) {
89 addr = (unsigned long) page_address(page);
90 if (exec)
91 flush_data_cache_page(addr);
92 clear_bit(PG_dcache_dirty, &(page)->flags);
93 }
94}
95
96static inline void setup_protection_map(void)
97{
98 protection_map[0] = PAGE_NONE;
99 protection_map[1] = PAGE_READONLY;
100 protection_map[2] = PAGE_COPY;
101 protection_map[3] = PAGE_COPY;
102 protection_map[4] = PAGE_READONLY;
103 protection_map[5] = PAGE_READONLY;
104 protection_map[6] = PAGE_COPY;
105 protection_map[7] = PAGE_COPY;
106 protection_map[8] = PAGE_NONE;
107 protection_map[9] = PAGE_READONLY;
108 protection_map[10] = PAGE_SHARED;
109 protection_map[11] = PAGE_SHARED;
110 protection_map[12] = PAGE_READONLY;
111 protection_map[13] = PAGE_READONLY;
112 protection_map[14] = PAGE_SHARED;
113 protection_map[15] = PAGE_SHARED;
114}
115
116void __devinit cpu_cache_init(void)
117{
118 setup_protection_map();
119}
120
121void flush_icache_all(void)
122{
123 __asm__ __volatile__(
124 "la r8, flush_icache_all\n"
125 "cache 0x10, [r8, 0]\n"
126 "nop\nnop\nnop\nnop\nnop\nnop\n"
127 : : : "r8");
128}
129
130void flush_dcache_all(void)
131{
132 __asm__ __volatile__(
133 "la r8, flush_dcache_all\n"
134 "cache 0x1f, [r8, 0]\n"
135 "nop\nnop\nnop\nnop\nnop\nnop\n"
136 "cache 0x1a, [r8, 0]\n"
137 "nop\nnop\nnop\nnop\nnop\nnop\n"
138 : : : "r8");
139}
140
141void flush_cache_all(void)
142{
143 __asm__ __volatile__(
144 "la r8, flush_cache_all\n"
145 "cache 0x10, [r8, 0]\n"
146 "nop\nnop\nnop\nnop\nnop\nnop\n"
147 "cache 0x1f, [r8, 0]\n"
148 "nop\nnop\nnop\nnop\nnop\nnop\n"
149 "cache 0x1a, [r8, 0]\n"
150 "nop\nnop\nnop\nnop\nnop\nnop\n"
151 : : : "r8");
152}
153
154void flush_cache_mm(struct mm_struct *mm)
155{
156 if (!(mm->context))
157 return;
158 flush_cache_all();
159}
160
161
162
163
164
165
166
167
168
169
170
171void flush_cache_range(struct vm_area_struct *vma,
172 unsigned long start, unsigned long end)
173{
174 struct mm_struct *mm = vma->vm_mm;
175 int exec = vma->vm_flags & VM_EXEC;
176 pgd_t *pgdp;
177 pud_t *pudp;
178 pmd_t *pmdp;
179 pte_t *ptep;
180
181 if (!(mm->context))
182 return;
183
184 pgdp = pgd_offset(mm, start);
185 pudp = pud_offset(pgdp, start);
186 pmdp = pmd_offset(pudp, start);
187 ptep = pte_offset(pmdp, start);
188
189 while (start <= end) {
190 unsigned long tmpend;
191 pgdp = pgd_offset(mm, start);
192 pudp = pud_offset(pgdp, start);
193 pmdp = pmd_offset(pudp, start);
194 ptep = pte_offset(pmdp, start);
195
196 if (!(pte_val(*ptep) & _PAGE_PRESENT)) {
197 start = (start + PAGE_SIZE) & ~(PAGE_SIZE - 1);
198 continue;
199 }
200 tmpend = (start | (PAGE_SIZE-1)) > end ?
201 end : (start | (PAGE_SIZE-1));
202
203 flush_dcache_range(start, tmpend);
204 if (exec)
205 flush_icache_range(start, tmpend);
206 start = (start + PAGE_SIZE) & ~(PAGE_SIZE - 1);
207 }
208}
209
210void flush_cache_page(struct vm_area_struct *vma,
211 unsigned long addr, unsigned long pfn)
212{
213 int exec = vma->vm_flags & VM_EXEC;
214 unsigned long kaddr = 0xa0000000 | (pfn << PAGE_SHIFT);
215
216 flush_dcache_range(kaddr, kaddr + PAGE_SIZE);
217
218 if (exec)
219 flush_icache_range(kaddr, kaddr + PAGE_SIZE);
220}
221
222void flush_cache_sigtramp(unsigned long addr)
223{
224 __asm__ __volatile__(
225 "cache 0x02, [%0, 0]\n"
226 "nop\nnop\nnop\nnop\nnop\n"
227 "cache 0x02, [%0, 0x4]\n"
228 "nop\nnop\nnop\nnop\nnop\n"
229
230 "cache 0x0d, [%0, 0]\n"
231 "nop\nnop\nnop\nnop\nnop\n"
232 "cache 0x0d, [%0, 0x4]\n"
233 "nop\nnop\nnop\nnop\nnop\n"
234
235 "cache 0x1a, [%0, 0]\n"
236 "nop\nnop\nnop\nnop\nnop\n"
237 : : "r" (addr));
238}
239
240
241
242
243
244
245void flush_dcache_range(unsigned long start, unsigned long end)
246{
247 int size, i;
248
249 start = start & ~(L1_CACHE_BYTES - 1);
250 end = end & ~(L1_CACHE_BYTES - 1);
251 size = end - start;
252
253 for (i = 0; i < size; i += L1_CACHE_BYTES) {
254 __asm__ __volatile__(
255 "cache 0x0e, [%0, 0]\n"
256 "nop\nnop\nnop\nnop\nnop\n"
257 "cache 0x1a, [%0, 0]\n"
258 "nop\nnop\nnop\nnop\nnop\n"
259 : : "r" (start));
260 start += L1_CACHE_BYTES;
261 }
262}
263
264void flush_icache_range(unsigned long start, unsigned long end)
265{
266 int size, i;
267 start = start & ~(L1_CACHE_BYTES - 1);
268 end = end & ~(L1_CACHE_BYTES - 1);
269
270 size = end - start;
271
272 for (i = 0; i < size; i += L1_CACHE_BYTES) {
273 __asm__ __volatile__(
274 "cache 0x02, [%0, 0]\n"
275 "nop\nnop\nnop\nnop\nnop\n"
276 : : "r" (start));
277 start += L1_CACHE_BYTES;
278 }
279}
280