VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / arch / parisc / kernel / cache.c
1 /* $Id: cache.c,v 1.4 2000/01/25 00:11:38 prumpf Exp $
2  *
3  * This file is subject to the terms and conditions of the GNU General Public
4  * License.  See the file "COPYING" in the main directory of this archive
5  * for more details.
6  *
7  * Copyright (C) 1999 Helge Deller (07-13-1999)
8  * Copyright (C) 1999 SuSE GmbH Nuernberg
9  * Copyright (C) 2000 Philipp Rumpf (prumpf@tux.org)
10  *
11  * Cache and TLB management
12  *
13  */
14  
15 #include <linux/init.h>
16 #include <linux/kernel.h>
17 #include <linux/mm.h>
18 #include <linux/module.h>
19 #include <linux/seq_file.h>
20 #include <linux/pagemap.h>
21
22 #include <asm/pdc.h>
23 #include <asm/cache.h>
24 #include <asm/cacheflush.h>
25 #include <asm/tlbflush.h>
26 #include <asm/system.h>
27 #include <asm/page.h>
28 #include <asm/pgalloc.h>
29 #include <asm/processor.h>
30
31 int split_tlb;
32 int dcache_stride;
33 int icache_stride;
34 EXPORT_SYMBOL(dcache_stride);
35
36 struct pdc_cache_info cache_info;
37 #ifndef CONFIG_PA20
38 static struct pdc_btlb_info btlb_info;
39 #endif
40
41 #ifdef CONFIG_SMP
42 void
43 flush_data_cache(void)
44 {
45         on_each_cpu((void (*)(void *))flush_data_cache_local, NULL, 1, 1);
46 }
47 #endif
48
49 void
50 flush_cache_all_local(void)
51 {
52         flush_instruction_cache_local();
53         flush_data_cache_local();
54 }
55 EXPORT_SYMBOL(flush_cache_all_local);
56
57 /* flushes EVERYTHING (tlb & cache) */
58
59 void
60 flush_all_caches(void)
61 {
62         flush_cache_all();
63         flush_tlb_all();
64 }
65 EXPORT_SYMBOL(flush_all_caches);
66
67 void
68 update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte)
69 {
70         struct page *page = pte_page(pte);
71
72         if (pfn_valid(page_to_pfn(page)) && page_mapping(page) &&
73             test_bit(PG_dcache_dirty, &page->flags)) {
74
75                 flush_kernel_dcache_page(page_address(page));
76                 clear_bit(PG_dcache_dirty, &page->flags);
77         }
78 }
79
80 void
81 show_cache_info(struct seq_file *m)
82 {
83         seq_printf(m, "I-cache\t\t: %ld KB\n", 
84                 cache_info.ic_size/1024 );
85         seq_printf(m, "D-cache\t\t: %ld KB (%s%s, %d-way associative)\n", 
86                 cache_info.dc_size/1024,
87                 (cache_info.dc_conf.cc_wt ? "WT":"WB"),
88                 (cache_info.dc_conf.cc_sh ? ", shared I/D":""),
89                 (cache_info.dc_conf.cc_assoc)
90         );
91
92         seq_printf(m, "ITLB entries\t: %ld\n" "DTLB entries\t: %ld%s\n",
93                 cache_info.it_size,
94                 cache_info.dt_size,
95                 cache_info.dt_conf.tc_sh ? " - shared with ITLB":""
96         );
97                 
98 #ifndef CONFIG_PA20
99         /* BTLB - Block TLB */
100         if (btlb_info.max_size==0) {
101                 seq_printf(m, "BTLB\t\t: not supported\n" );
102         } else {
103                 seq_printf(m, 
104                 "BTLB fixed\t: max. %d pages, pagesize=%d (%dMB)\n"
105                 "BTLB fix-entr.\t: %d instruction, %d data (%d combined)\n"
106                 "BTLB var-entr.\t: %d instruction, %d data (%d combined)\n",
107                 btlb_info.max_size, (int)4096,
108                 btlb_info.max_size>>8,
109                 btlb_info.fixed_range_info.num_i,
110                 btlb_info.fixed_range_info.num_d,
111                 btlb_info.fixed_range_info.num_comb, 
112                 btlb_info.variable_range_info.num_i,
113                 btlb_info.variable_range_info.num_d,
114                 btlb_info.variable_range_info.num_comb
115                 );
116         }
117 #endif
118 }
119
120 void __init 
121 parisc_cache_init(void)
122 {
123         if (pdc_cache_info(&cache_info) < 0)
124                 panic("parisc_cache_init: pdc_cache_info failed");
125
126 #if 0
127         printk("ic_size %lx dc_size %lx it_size %lx\n",
128                 cache_info.ic_size,
129                 cache_info.dc_size,
130                 cache_info.it_size);
131
132         printk("DC  base 0x%lx stride 0x%lx count 0x%lx loop 0x%lx\n",
133                 cache_info.dc_base,
134                 cache_info.dc_stride,
135                 cache_info.dc_count,
136                 cache_info.dc_loop);
137
138         printk("dc_conf = 0x%lx  alias %d blk %d line %d shift %d\n",
139                 *(unsigned long *) (&cache_info.dc_conf),
140                 cache_info.dc_conf.cc_alias,
141                 cache_info.dc_conf.cc_block,
142                 cache_info.dc_conf.cc_line,
143                 cache_info.dc_conf.cc_shift);
144         printk("        wt %d sh %d cst %d assoc %d\n",
145                 cache_info.dc_conf.cc_wt,
146                 cache_info.dc_conf.cc_sh,
147                 cache_info.dc_conf.cc_cst,
148                 cache_info.dc_conf.cc_assoc);
149
150         printk("IC  base 0x%lx stride 0x%lx count 0x%lx loop 0x%lx\n",
151                 cache_info.ic_base,
152                 cache_info.ic_stride,
153                 cache_info.ic_count,
154                 cache_info.ic_loop);
155
156         printk("ic_conf = 0x%lx  alias %d blk %d line %d shift %d\n",
157                 *(unsigned long *) (&cache_info.ic_conf),
158                 cache_info.ic_conf.cc_alias,
159                 cache_info.ic_conf.cc_block,
160                 cache_info.ic_conf.cc_line,
161                 cache_info.ic_conf.cc_shift);
162         printk("        wt %d sh %d cst %d assoc %d\n",
163                 cache_info.ic_conf.cc_wt,
164                 cache_info.ic_conf.cc_sh,
165                 cache_info.ic_conf.cc_cst,
166                 cache_info.ic_conf.cc_assoc);
167
168         printk("D-TLB conf: sh %d page %d cst %d aid %d pad1 %d \n",
169                 cache_info.dt_conf.tc_sh,
170                 cache_info.dt_conf.tc_page,
171                 cache_info.dt_conf.tc_cst,
172                 cache_info.dt_conf.tc_aid,
173                 cache_info.dt_conf.tc_pad1);
174
175         printk("I-TLB conf: sh %d page %d cst %d aid %d pad1 %d \n",
176                 cache_info.it_conf.tc_sh,
177                 cache_info.it_conf.tc_page,
178                 cache_info.it_conf.tc_cst,
179                 cache_info.it_conf.tc_aid,
180                 cache_info.it_conf.tc_pad1);
181 #endif
182
183         split_tlb = 0;
184         if (cache_info.dt_conf.tc_sh == 0 || cache_info.dt_conf.tc_sh == 2) {
185                 if (cache_info.dt_conf.tc_sh == 2)
186                         printk(KERN_WARNING "Unexpected TLB configuration. "
187                         "Will flush I/D separately (could be optimized).\n");
188
189                 split_tlb = 1;
190         }
191
192         /* "New and Improved" version from Jim Hull 
193          *      (1 << (cc_block-1)) * (cc_line << (4 + cnf.cc_shift))
194          */
195 #define CAFL_STRIDE(cnf) (cnf.cc_line << (3 + cnf.cc_block + cnf.cc_shift))
196         dcache_stride = CAFL_STRIDE(cache_info.dc_conf);
197         icache_stride = CAFL_STRIDE(cache_info.ic_conf);
198 #undef CAFL_STRIDE
199
200 #ifndef CONFIG_PA20
201         if (pdc_btlb_info(&btlb_info) < 0) {
202                 memset(&btlb_info, 0, sizeof btlb_info);
203         }
204 #endif
205
206         if ((boot_cpu_data.pdc.capabilities & PDC_MODEL_NVA_MASK) ==
207                                                 PDC_MODEL_NVA_UNSUPPORTED) {
208                 printk(KERN_WARNING "parisc_cache_init: Only equivalent aliasing supported!\n");
209 #if 0
210                 panic("SMP kernel required to avoid non-equivalent aliasing");
211 #endif
212         }
213 }
214
215 void disable_sr_hashing(void)
216 {
217         int srhash_type;
218
219         switch (boot_cpu_data.cpu_type) {
220         case pcx: /* We shouldn't get this far.  setup.c should prevent it. */
221                 BUG();
222                 return;
223
224         case pcxs:
225         case pcxt:
226         case pcxt_:
227                 srhash_type = SRHASH_PCXST;
228                 break;
229
230         case pcxl:
231                 srhash_type = SRHASH_PCXL;
232                 break;
233
234         case pcxl2: /* pcxl2 doesn't support space register hashing */
235                 return;
236
237         default: /* Currently all PA2.0 machines use the same ins. sequence */
238                 srhash_type = SRHASH_PA20;
239                 break;
240         }
241
242         disable_sr_hashing_asm(srhash_type);
243 }
244
245 void flush_dcache_page(struct page *page)
246 {
247         struct address_space *mapping = page_mapping(page);
248         struct vm_area_struct *mpnt = NULL;
249         struct prio_tree_iter iter;
250         unsigned long offset;
251         unsigned long addr;
252         pgoff_t pgoff;
253         pte_t *pte;
254         unsigned long pfn = page_to_pfn(page);
255
256
257         if (mapping && !mapping_mapped(mapping)) {
258                 set_bit(PG_dcache_dirty, &page->flags);
259                 return;
260         }
261
262         flush_kernel_dcache_page(page_address(page));
263
264         if (!mapping)
265                 return;
266
267         pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
268
269         /* We have carefully arranged in arch_get_unmapped_area() that
270          * *any* mappings of a file are always congruently mapped (whether
271          * declared as MAP_PRIVATE or MAP_SHARED), so we only need
272          * to flush one address here for them all to become coherent */
273
274         flush_dcache_mmap_lock(mapping);
275         while ((mpnt = vma_prio_tree_next(mpnt, &mapping->i_mmap,
276                                         &iter, pgoff, pgoff)) != NULL) {
277                 offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
278                 addr = mpnt->vm_start + offset;
279
280                 /* Flush instructions produce non access tlb misses.
281                  * On PA, we nullify these instructions rather than
282                  * taking a page fault if the pte doesn't exist.
283                  * This is just for speed.  If the page translation
284                  * isn't there, there's no point exciting the
285                  * nadtlb handler into a nullification frenzy */
286
287
288                 if(!(pte = translation_exists(mpnt, addr)))
289                         continue;
290
291                 /* make sure we really have this page: the private
292                  * mappings may cover this area but have COW'd this
293                  * particular page */
294                 if(pte_pfn(*pte) != pfn)
295                         continue;
296
297                 __flush_cache_page(mpnt, addr);
298
299                 break;
300         }
301         flush_dcache_mmap_unlock(mapping);
302 }
303 EXPORT_SYMBOL(flush_dcache_page);
304
305 /* Defined in arch/parisc/kernel/pacache.S */
306 EXPORT_SYMBOL(flush_kernel_dcache_range_asm);
307 EXPORT_SYMBOL(flush_kernel_dcache_page);
308 EXPORT_SYMBOL(flush_data_cache_local);
309 EXPORT_SYMBOL(flush_kernel_icache_range_asm);