v2.4.8 -> v2.4.8.1
[opensuse:kernel.git] / include / asm-arm / proc-armv / cache.h
1 /*
2  *  linux/include/asm-arm/proc-armv/cache.h
3  *
4  *  Copyright (C) 1999-2001 Russell King
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10 #include <asm/mman.h>
11
12 /*
13  * This flag is used to indicate that the page pointed to by a pte
14  * is dirty and requires cleaning before returning it to the user.
15  */
16 #define PG_dcache_dirty PG_arch_1
17
18 /*
19  * Cache handling for 32-bit ARM processors.
20  *
21  * Note that on ARM, we have a more accurate specification than that
22  * Linux's "flush".  We therefore do not use "flush" here, but instead
23  * use:
24  *
25  * clean:      the act of pushing dirty cache entries out to memory.
26  * invalidate: the act of discarding data held within the cache,
27  *             whether it is dirty or not.
28  */
29
30 /*
31  * Generic I + D cache
32  */
33 #define flush_cache_all()                                               \
34         do {                                                            \
35                 cpu_cache_clean_invalidate_all();                       \
36         } while (0)
37
38 /* This is always called for current->mm */
39 #define flush_cache_mm(_mm)                                             \
40         do {                                                            \
41                 if ((_mm) == current->active_mm)                        \
42                         cpu_cache_clean_invalidate_all();               \
43         } while (0)
44
45 #define flush_cache_range(_mm,_start,_end)                              \
46         do {                                                            \
47                 if ((_mm) == current->mm)                               \
48                         cpu_cache_clean_invalidate_range((_start), (_end), 1); \
49         } while (0)
50
51 #define flush_cache_page(_vma,_vmaddr)                                  \
52         do {                                                            \
53                 if ((_vma)->vm_mm == current->mm) {                     \
54                         cpu_cache_clean_invalidate_range((_vmaddr),     \
55                                 (_vmaddr) + PAGE_SIZE,                  \
56                                 ((_vma)->vm_flags & VM_EXEC));          \
57                 } \
58         } while (0)
59
60 /*
61  * This flushes back any buffered write data.  We have to clean the entries
62  * in the cache for this page.  This does not invalidate either I or D caches.
63  *
64  * Called from:
65  * 1. mm/filemap.c:filemap_nopage
66  * 2. mm/filemap.c:filemap_nopage
67  *    [via do_no_page - ok]
68  *
69  * 3. mm/memory.c:break_cow
70  *    [copy_cow_page doesn't do anything to the cache; insufficient cache
71  *     handling.  Need to add flush_dcache_page() here]
72  *
73  * 4. mm/memory.c:do_swap_page
74  *    [read_swap_cache_async doesn't do anything to the cache: insufficient
75  *     cache handling.  Need to add flush_dcache_page() here]
76  *
77  * 5. mm/memory.c:do_anonymous_page
78  *    [zero page, never written by kernel - ok]
79  *
80  * 6. mm/memory.c:do_no_page
81  *    [we will be calling update_mmu_cache, which will catch on PG_dcache_dirty]
82  *
83  * 7. mm/shmem.c:shmem_nopage
84  * 8. mm/shmem.c:shmem_nopage
85  *    [via do_no_page - ok]
86  *
87  * 9. fs/exec.c:put_dirty_page
88  *    [we call flush_dcache_page prior to this, which will flush out the
89  *     kernel virtual addresses from the dcache - ok]
90  */
91 static __inline__ void flush_page_to_ram(struct page *page)
92 {
93         cpu_flush_ram_page(page_address(page));
94 }
95
96 /*
97  * D cache only
98  */
99
100 #define invalidate_dcache_range(_s,_e)  cpu_dcache_invalidate_range((_s),(_e))
101 #define clean_dcache_range(_s,_e)       cpu_dcache_clean_range((_s),(_e))
102 #define flush_dcache_range(_s,_e)       cpu_cache_clean_invalidate_range((_s),(_e),0)
103
104 /*
105  * flush_dcache_page is used when the kernel has written to the page
106  * cache page at virtual address page->virtual.
107  *
108  * If this page isn't mapped (ie, page->mapping = NULL), or it has
109  * userspace mappings (page->mapping->i_mmap or page->mapping->i_mmap_shared)
110  * then we _must_ always clean + invalidate the dcache entries associated
111  * with the kernel mapping.
112  *
113  * Otherwise we can defer the operation, and clean the cache when we are
114  * about to change to user space.  This is the same method as used on SPARC64.
115  * See update_mmu_cache for the user space part.
116  */
117 static inline void flush_dcache_page(struct page *page)
118 {
119         if (page->mapping && !(page->mapping->i_mmap) &&
120              !(page->mapping->i_mmap_shared))
121                 set_bit(PG_dcache_dirty, &page->flags);
122         else {
123                 unsigned long virt = (unsigned long)page_address(page);
124                 cpu_cache_clean_invalidate_range(virt, virt + PAGE_SIZE, 0);
125         }
126 }
127
128 #define clean_dcache_entry(_s)          cpu_dcache_clean_entry((unsigned long)(_s))
129
130 /*
131  * I cache only
132  */
133 #define flush_icache_range(_s,_e)                                       \
134         do {                                                            \
135                 cpu_icache_invalidate_range((_s), (_e));                \
136         } while (0)
137
138 /*
139  * This function is misnamed IMHO.  There are three places where it
140  * is called, each of which is preceded immediately by a call to
141  * flush_page_to_ram:
142  *
143  *  1. kernel/ptrace.c:access_one_page
144  *     called after we have written to the kernel view of a user page.
145  *     The user page has been expundged from the cache by flush_cache_page.
146  *     [we don't need to do anything here if we add a call to
147  *      flush_dcache_page]
148  *
149  *  2. mm/memory.c:do_swap_page
150  *     called after we have (possibly) written to the kernel view of a
151  *     user page, which has previously been removed (ie, has been through
152  *     the swap cache).
153  *     [if the flush_page_to_ram() conditions are satisfied, then ok]
154  *
155  *  3. mm/memory.c:do_no_page
156  *     [if the flush_page_to_ram() conditions are satisfied, then ok]
157  *
158  * Invalidating the icache at the kernels virtual page isn't really
159  * going to do us much good, since we wouldn't have executed any
160  * instructions there.
161  */
162 #define flush_icache_page(vma,pg)       do { } while (0)
163
164 /*
165  * Old ARM MEMC stuff.  This supports the reversed mapping handling that
166  * we have on the older 26-bit machines.  We don't have a MEMC chip, so...
167  */
168 #define memc_update_all()               do { } while (0)
169 #define memc_update_mm(mm)              do { } while (0)
170 #define memc_update_addr(mm,pte,log)    do { } while (0)
171 #define memc_clear(mm,physaddr)         do { } while (0)
172
173 /*
174  * TLB flushing.
175  *
176  *  - flush_tlb_all()                   flushes all processes TLBs
177  *  - flush_tlb_mm(mm)                  flushes the specified mm context TLB's
178  *  - flush_tlb_page(vma, vmaddr)       flushes TLB for specified page
179  *  - flush_tlb_range(mm, start, end)   flushes TLB for specified range of pages
180  *
181  * We drain the write buffer in here to ensure that the page tables in ram
182  * are really up to date.  It is more efficient to do this here...
183  */
184
185 /*
186  * Notes:
187  *  current->active_mm is the currently active memory description.
188  *  current->mm == NULL iff we are lazy.
189  */
190 #define flush_tlb_all()                                                 \
191         do {                                                            \
192                 cpu_tlb_invalidate_all();                               \
193         } while (0)
194
195 /*
196  * Flush all user virtual address space translations described by `_mm'.
197  *
198  * Currently, this is always called for current->mm, which should be
199  * the same as current->active_mm.  This is currently not be called for
200  * the lazy TLB case.
201  */
202 #define flush_tlb_mm(_mm)                                               \
203         do {                                                            \
204                 if ((_mm) == current->active_mm)                        \
205                         cpu_tlb_invalidate_all();                       \
206         } while (0)
207
208 /*
209  * Flush the specified range of user virtual address space translations.
210  *
211  * _mm may not be current->active_mm, but may not be NULL.
212  */
213 #define flush_tlb_range(_mm,_start,_end)                                \
214         do {                                                            \
215                 if ((_mm) == current->active_mm)                        \
216                         cpu_tlb_invalidate_range((_start), (_end));     \
217         } while (0)
218
219 /*
220  * Flush the specified user virtual address space translation.
221  */
222 #define flush_tlb_page(_vma,_page)                                      \
223         do {                                                            \
224                 if ((_vma)->vm_mm == current->active_mm)                \
225                         cpu_tlb_invalidate_page((_page),                \
226                                  ((_vma)->vm_flags & VM_EXEC));         \
227         } while (0)
228
229 /*
230  * if PG_dcache_dirty is set for the page, we need to ensure that any
231  * cache entries for the kernels virtual memory range are written
232  * back to the page.
233  */
234 extern void check_pgcache_dirty(struct page *page);
235
236 #define update_mmu_cache(vma,address,pte) check_pgcache_dirty(pte_page(pte))
237