]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - arch/parisc/kernel/cache.c
parisc: optimize mtsp(0,sr) inline assembly
[mirror_ubuntu-hirsute-kernel.git] / arch / parisc / kernel / cache.c
CommitLineData
071327ec 1/*
1da177e4
LT
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
67a5a59d 6 * Copyright (C) 1999-2006 Helge Deller <deller@gmx.de> (07-13-1999)
1da177e4
LT
7 * Copyright (C) 1999 SuSE GmbH Nuernberg
8 * Copyright (C) 2000 Philipp Rumpf (prumpf@tux.org)
9 *
10 * Cache and TLB management
11 *
12 */
13
14#include <linux/init.h>
15#include <linux/kernel.h>
16#include <linux/mm.h>
17#include <linux/module.h>
18#include <linux/seq_file.h>
19#include <linux/pagemap.h>
e8edc6e0 20#include <linux/sched.h>
1da177e4
LT
21#include <asm/pdc.h>
22#include <asm/cache.h>
23#include <asm/cacheflush.h>
24#include <asm/tlbflush.h>
1da177e4
LT
25#include <asm/page.h>
26#include <asm/pgalloc.h>
27#include <asm/processor.h>
2464212f 28#include <asm/sections.h>
f311847c 29#include <asm/shmparam.h>
1da177e4 30
8039de10
HD
31int split_tlb __read_mostly;
32int dcache_stride __read_mostly;
33int icache_stride __read_mostly;
1da177e4
LT
34EXPORT_SYMBOL(dcache_stride);
35
f311847c
JB
36void flush_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr);
37EXPORT_SYMBOL(flush_dcache_page_asm);
38void flush_icache_page_asm(unsigned long phys_addr, unsigned long vaddr);
39
1da177e4 40
1da177e4
LT
41/* On some machines (e.g. ones with the Merced bus), there can be
42 * only a single PxTLB broadcast at a time; this must be guaranteed
43 * by software. We put a spinlock around all TLB flushes to
44 * ensure this.
45 */
46DEFINE_SPINLOCK(pa_tlb_lock);
1da177e4 47
8039de10 48struct pdc_cache_info cache_info __read_mostly;
1da177e4 49#ifndef CONFIG_PA20
8039de10 50static struct pdc_btlb_info btlb_info __read_mostly;
1da177e4
LT
51#endif
52
53#ifdef CONFIG_SMP
54void
55flush_data_cache(void)
56{
15c8b6c1 57 on_each_cpu(flush_data_cache_local, NULL, 1);
1da177e4
LT
58}
59void
60flush_instruction_cache(void)
61{
15c8b6c1 62 on_each_cpu(flush_instruction_cache_local, NULL, 1);
1da177e4
LT
63}
64#endif
65
66void
67flush_cache_all_local(void)
68{
1b2425e3
MW
69 flush_instruction_cache_local(NULL);
70 flush_data_cache_local(NULL);
1da177e4
LT
71}
72EXPORT_SYMBOL(flush_cache_all_local);
73
1da177e4 74void
4b3073e1 75update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
1da177e4 76{
4b3073e1 77 struct page *page = pte_page(*ptep);
1da177e4
LT
78
79 if (pfn_valid(page_to_pfn(page)) && page_mapping(page) &&
80 test_bit(PG_dcache_dirty, &page->flags)) {
81
ba575833 82 flush_kernel_dcache_page(page);
1da177e4 83 clear_bit(PG_dcache_dirty, &page->flags);
20f4d3cb
JB
84 } else if (parisc_requires_coherency())
85 flush_kernel_dcache_page(page);
1da177e4
LT
86}
87
88void
89show_cache_info(struct seq_file *m)
90{
e5a2e7fd
KM
91 char buf[32];
92
1da177e4
LT
93 seq_printf(m, "I-cache\t\t: %ld KB\n",
94 cache_info.ic_size/1024 );
2f75c12c 95 if (cache_info.dc_loop != 1)
e5a2e7fd
KM
96 snprintf(buf, 32, "%lu-way associative", cache_info.dc_loop);
97 seq_printf(m, "D-cache\t\t: %ld KB (%s%s, %s)\n",
1da177e4
LT
98 cache_info.dc_size/1024,
99 (cache_info.dc_conf.cc_wt ? "WT":"WB"),
100 (cache_info.dc_conf.cc_sh ? ", shared I/D":""),
e5a2e7fd 101 ((cache_info.dc_loop == 1) ? "direct mapped" : buf));
1da177e4
LT
102 seq_printf(m, "ITLB entries\t: %ld\n" "DTLB entries\t: %ld%s\n",
103 cache_info.it_size,
104 cache_info.dt_size,
105 cache_info.dt_conf.tc_sh ? " - shared with ITLB":""
106 );
107
108#ifndef CONFIG_PA20
109 /* BTLB - Block TLB */
110 if (btlb_info.max_size==0) {
111 seq_printf(m, "BTLB\t\t: not supported\n" );
112 } else {
113 seq_printf(m,
114 "BTLB fixed\t: max. %d pages, pagesize=%d (%dMB)\n"
115 "BTLB fix-entr.\t: %d instruction, %d data (%d combined)\n"
116 "BTLB var-entr.\t: %d instruction, %d data (%d combined)\n",
117 btlb_info.max_size, (int)4096,
118 btlb_info.max_size>>8,
119 btlb_info.fixed_range_info.num_i,
120 btlb_info.fixed_range_info.num_d,
121 btlb_info.fixed_range_info.num_comb,
122 btlb_info.variable_range_info.num_i,
123 btlb_info.variable_range_info.num_d,
124 btlb_info.variable_range_info.num_comb
125 );
126 }
127#endif
128}
129
130void __init
131parisc_cache_init(void)
132{
133 if (pdc_cache_info(&cache_info) < 0)
134 panic("parisc_cache_init: pdc_cache_info failed");
135
136#if 0
137 printk("ic_size %lx dc_size %lx it_size %lx\n",
138 cache_info.ic_size,
139 cache_info.dc_size,
140 cache_info.it_size);
141
142 printk("DC base 0x%lx stride 0x%lx count 0x%lx loop 0x%lx\n",
143 cache_info.dc_base,
144 cache_info.dc_stride,
145 cache_info.dc_count,
146 cache_info.dc_loop);
147
148 printk("dc_conf = 0x%lx alias %d blk %d line %d shift %d\n",
149 *(unsigned long *) (&cache_info.dc_conf),
150 cache_info.dc_conf.cc_alias,
151 cache_info.dc_conf.cc_block,
152 cache_info.dc_conf.cc_line,
153 cache_info.dc_conf.cc_shift);
e5a2e7fd 154 printk(" wt %d sh %d cst %d hv %d\n",
1da177e4
LT
155 cache_info.dc_conf.cc_wt,
156 cache_info.dc_conf.cc_sh,
157 cache_info.dc_conf.cc_cst,
e5a2e7fd 158 cache_info.dc_conf.cc_hv);
1da177e4
LT
159
160 printk("IC base 0x%lx stride 0x%lx count 0x%lx loop 0x%lx\n",
161 cache_info.ic_base,
162 cache_info.ic_stride,
163 cache_info.ic_count,
164 cache_info.ic_loop);
165
166 printk("ic_conf = 0x%lx alias %d blk %d line %d shift %d\n",
167 *(unsigned long *) (&cache_info.ic_conf),
168 cache_info.ic_conf.cc_alias,
169 cache_info.ic_conf.cc_block,
170 cache_info.ic_conf.cc_line,
171 cache_info.ic_conf.cc_shift);
e5a2e7fd 172 printk(" wt %d sh %d cst %d hv %d\n",
1da177e4
LT
173 cache_info.ic_conf.cc_wt,
174 cache_info.ic_conf.cc_sh,
175 cache_info.ic_conf.cc_cst,
e5a2e7fd 176 cache_info.ic_conf.cc_hv);
1da177e4 177
a3bee03e 178 printk("D-TLB conf: sh %d page %d cst %d aid %d pad1 %d\n",
1da177e4
LT
179 cache_info.dt_conf.tc_sh,
180 cache_info.dt_conf.tc_page,
181 cache_info.dt_conf.tc_cst,
182 cache_info.dt_conf.tc_aid,
183 cache_info.dt_conf.tc_pad1);
184
a3bee03e 185 printk("I-TLB conf: sh %d page %d cst %d aid %d pad1 %d\n",
1da177e4
LT
186 cache_info.it_conf.tc_sh,
187 cache_info.it_conf.tc_page,
188 cache_info.it_conf.tc_cst,
189 cache_info.it_conf.tc_aid,
190 cache_info.it_conf.tc_pad1);
191#endif
192
193 split_tlb = 0;
194 if (cache_info.dt_conf.tc_sh == 0 || cache_info.dt_conf.tc_sh == 2) {
195 if (cache_info.dt_conf.tc_sh == 2)
196 printk(KERN_WARNING "Unexpected TLB configuration. "
197 "Will flush I/D separately (could be optimized).\n");
198
199 split_tlb = 1;
200 }
201
202 /* "New and Improved" version from Jim Hull
203 * (1 << (cc_block-1)) * (cc_line << (4 + cnf.cc_shift))
2464212f
SB
204 * The following CAFL_STRIDE is an optimized version, see
205 * http://lists.parisc-linux.org/pipermail/parisc-linux/2004-June/023625.html
206 * http://lists.parisc-linux.org/pipermail/parisc-linux/2004-June/023671.html
1da177e4
LT
207 */
208#define CAFL_STRIDE(cnf) (cnf.cc_line << (3 + cnf.cc_block + cnf.cc_shift))
209 dcache_stride = CAFL_STRIDE(cache_info.dc_conf);
210 icache_stride = CAFL_STRIDE(cache_info.ic_conf);
211#undef CAFL_STRIDE
212
213#ifndef CONFIG_PA20
214 if (pdc_btlb_info(&btlb_info) < 0) {
215 memset(&btlb_info, 0, sizeof btlb_info);
216 }
217#endif
218
219 if ((boot_cpu_data.pdc.capabilities & PDC_MODEL_NVA_MASK) ==
220 PDC_MODEL_NVA_UNSUPPORTED) {
221 printk(KERN_WARNING "parisc_cache_init: Only equivalent aliasing supported!\n");
222#if 0
223 panic("SMP kernel required to avoid non-equivalent aliasing");
224#endif
225 }
226}
227
228void disable_sr_hashing(void)
229{
a9d2d386
KM
230 int srhash_type, retval;
231 unsigned long space_bits;
1da177e4
LT
232
233 switch (boot_cpu_data.cpu_type) {
234 case pcx: /* We shouldn't get this far. setup.c should prevent it. */
235 BUG();
236 return;
237
238 case pcxs:
239 case pcxt:
240 case pcxt_:
241 srhash_type = SRHASH_PCXST;
242 break;
243
244 case pcxl:
245 srhash_type = SRHASH_PCXL;
246 break;
247
248 case pcxl2: /* pcxl2 doesn't support space register hashing */
249 return;
250
251 default: /* Currently all PA2.0 machines use the same ins. sequence */
252 srhash_type = SRHASH_PA20;
253 break;
254 }
255
256 disable_sr_hashing_asm(srhash_type);
a9d2d386
KM
257
258 retval = pdc_spaceid_bits(&space_bits);
259 /* If this procedure isn't implemented, don't panic. */
260 if (retval < 0 && retval != PDC_BAD_OPTION)
261 panic("pdc_spaceid_bits call failed.\n");
262 if (space_bits != 0)
263 panic("SpaceID hashing is still on!\n");
1da177e4
LT
264}
265
d6ce8626 266static inline void
f311847c
JB
267__flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr,
268 unsigned long physaddr)
d6ce8626 269{
027f27c4 270 preempt_disable();
f311847c
JB
271 flush_dcache_page_asm(physaddr, vmaddr);
272 if (vma->vm_flags & VM_EXEC)
273 flush_icache_page_asm(physaddr, vmaddr);
027f27c4 274 preempt_enable();
d6ce8626
RC
275}
276
1da177e4
LT
277void flush_dcache_page(struct page *page)
278{
279 struct address_space *mapping = page_mapping(page);
280 struct vm_area_struct *mpnt;
1da177e4 281 unsigned long offset;
f311847c 282 unsigned long addr, old_addr = 0;
1da177e4 283 pgoff_t pgoff;
1da177e4
LT
284
285 if (mapping && !mapping_mapped(mapping)) {
286 set_bit(PG_dcache_dirty, &page->flags);
287 return;
288 }
289
ba575833 290 flush_kernel_dcache_page(page);
1da177e4
LT
291
292 if (!mapping)
293 return;
294
295 pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
296
297 /* We have carefully arranged in arch_get_unmapped_area() that
298 * *any* mappings of a file are always congruently mapped (whether
299 * declared as MAP_PRIVATE or MAP_SHARED), so we only need
300 * to flush one address here for them all to become coherent */
301
302 flush_dcache_mmap_lock(mapping);
6b2dbba8 303 vma_interval_tree_foreach(mpnt, &mapping->i_mmap, pgoff, pgoff) {
1da177e4
LT
304 offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
305 addr = mpnt->vm_start + offset;
306
b7d45818
JB
307 /* The TLB is the engine of coherence on parisc: The
308 * CPU is entitled to speculate any page with a TLB
309 * mapping, so here we kill the mapping then flush the
310 * page along a special flush only alias mapping.
311 * This guarantees that the page is no-longer in the
312 * cache for any process and nor may it be
313 * speculatively read in (until the user or kernel
314 * specifically accesses it, of course) */
315
316 flush_tlb_page(mpnt, addr);
f311847c
JB
317 if (old_addr == 0 || (old_addr & (SHMLBA - 1)) != (addr & (SHMLBA - 1))) {
318 __flush_cache_page(mpnt, addr, page_to_phys(page));
319 if (old_addr)
b7d45818 320 printk(KERN_ERR "INEQUIVALENT ALIASES 0x%lx and 0x%lx in file %s\n", old_addr, addr, mpnt->vm_file ? (char *)mpnt->vm_file->f_path.dentry->d_name.name : "(null)");
f311847c 321 old_addr = addr;
92dc6fcc 322 }
1da177e4
LT
323 }
324 flush_dcache_mmap_unlock(mapping);
325}
326EXPORT_SYMBOL(flush_dcache_page);
327
328/* Defined in arch/parisc/kernel/pacache.S */
329EXPORT_SYMBOL(flush_kernel_dcache_range_asm);
ba575833 330EXPORT_SYMBOL(flush_kernel_dcache_page_asm);
1da177e4
LT
331EXPORT_SYMBOL(flush_data_cache_local);
332EXPORT_SYMBOL(flush_kernel_icache_range_asm);
333
1da177e4 334#define FLUSH_THRESHOLD 0x80000 /* 0.5MB */
8039de10 335int parisc_cache_flush_threshold __read_mostly = FLUSH_THRESHOLD;
1da177e4 336
d6ce8626 337void __init parisc_setup_cache_timing(void)
1da177e4
LT
338{
339 unsigned long rangetime, alltime;
1da177e4
LT
340 unsigned long size;
341
342 alltime = mfctl(16);
343 flush_data_cache();
344 alltime = mfctl(16) - alltime;
345
2464212f 346 size = (unsigned long)(_end - _text);
1da177e4 347 rangetime = mfctl(16);
2464212f 348 flush_kernel_dcache_range((unsigned long)_text, size);
1da177e4
LT
349 rangetime = mfctl(16) - rangetime;
350
351 printk(KERN_DEBUG "Whole cache flush %lu cycles, flushing %lu bytes %lu cycles\n",
352 alltime, size, rangetime);
353
354 /* Racy, but if we see an intermediate value, it's ok too... */
355 parisc_cache_flush_threshold = size * alltime / rangetime;
356
357 parisc_cache_flush_threshold = (parisc_cache_flush_threshold + L1_CACHE_BYTES - 1) &~ (L1_CACHE_BYTES - 1);
358 if (!parisc_cache_flush_threshold)
359 parisc_cache_flush_threshold = FLUSH_THRESHOLD;
360
d6ce8626
RC
361 if (parisc_cache_flush_threshold > cache_info.dc_size)
362 parisc_cache_flush_threshold = cache_info.dc_size;
363
67a5a59d 364 printk(KERN_INFO "Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus());
1da177e4 365}
20f4d3cb 366
76334539
JDA
367extern void purge_kernel_dcache_page_asm(unsigned long);
368extern void clear_user_page_asm(void *, unsigned long);
369extern void copy_user_page_asm(void *, void *, unsigned long);
20f4d3cb
JB
370
371void flush_kernel_dcache_page_addr(void *addr)
372{
e82a3b75
HD
373 unsigned long flags;
374
20f4d3cb 375 flush_kernel_dcache_page_asm(addr);
e82a3b75 376 purge_tlb_start(flags);
20f4d3cb 377 pdtlb_kernel(addr);
e82a3b75 378 purge_tlb_end(flags);
20f4d3cb
JB
379}
380EXPORT_SYMBOL(flush_kernel_dcache_page_addr);
381
76334539
JDA
382void clear_user_page(void *vto, unsigned long vaddr, struct page *page)
383{
384 clear_page_asm(vto);
385 if (!parisc_requires_coherency())
386 flush_kernel_dcache_page_asm(vto);
387}
388EXPORT_SYMBOL(clear_user_page);
389
20f4d3cb 390void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
76334539 391 struct page *pg)
20f4d3cb 392{
76334539
JDA
393 /* Copy using kernel mapping. No coherency is needed
394 (all in kmap/kunmap) on machines that don't support
395 non-equivalent aliasing. However, the `from' page
396 needs to be flushed before it can be accessed through
397 the kernel mapping. */
398 preempt_disable();
399 flush_dcache_page_asm(__pa(vfrom), vaddr);
400 preempt_enable();
401 copy_page_asm(vto, vfrom);
20f4d3cb
JB
402 if (!parisc_requires_coherency())
403 flush_kernel_dcache_page_asm(vto);
404}
405EXPORT_SYMBOL(copy_user_page);
406
407#ifdef CONFIG_PA8X00
408
409void kunmap_parisc(void *addr)
410{
411 if (parisc_requires_coherency())
412 flush_kernel_dcache_page_addr(addr);
413}
414EXPORT_SYMBOL(kunmap_parisc);
415#endif
d6ce8626 416
7139bc15
JDA
417void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
418{
419 unsigned long flags;
420
421 /* Note: purge_tlb_entries can be called at startup with
422 no context. */
423
7139bc15 424 purge_tlb_start(flags);
bda079d3 425 mtsp(mm->context, 1);
7139bc15
JDA
426 pdtlb(addr);
427 pitlb(addr);
428 purge_tlb_end(flags);
7139bc15
JDA
429}
430EXPORT_SYMBOL(purge_tlb_entries);
431
d6ce8626
RC
432void __flush_tlb_range(unsigned long sid, unsigned long start,
433 unsigned long end)
434{
435 unsigned long npages;
436
437 npages = ((end - (start & PAGE_MASK)) + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
438 if (npages >= 512) /* 2MB of space: arbitrary, should be tuned */
439 flush_tlb_all();
440 else {
e82a3b75
HD
441 unsigned long flags;
442
d6ce8626 443 mtsp(sid, 1);
e82a3b75 444 purge_tlb_start(flags);
d6ce8626
RC
445 if (split_tlb) {
446 while (npages--) {
447 pdtlb(start);
448 pitlb(start);
449 start += PAGE_SIZE;
450 }
451 } else {
452 while (npages--) {
453 pdtlb(start);
454 start += PAGE_SIZE;
455 }
456 }
e82a3b75 457 purge_tlb_end(flags);
d6ce8626
RC
458 }
459}
460
461static void cacheflush_h_tmp_function(void *dummy)
462{
463 flush_cache_all_local();
464}
465
466void flush_cache_all(void)
467{
15c8b6c1 468 on_each_cpu(cacheflush_h_tmp_function, NULL, 1);
d6ce8626
RC
469}
470
6d2439d9
JDA
471static inline unsigned long mm_total_size(struct mm_struct *mm)
472{
473 struct vm_area_struct *vma;
474 unsigned long usize = 0;
475
476 for (vma = mm->mmap; vma; vma = vma->vm_next)
477 usize += vma->vm_end - vma->vm_start;
478 return usize;
479}
480
481static inline pte_t *get_ptep(pgd_t *pgd, unsigned long addr)
482{
483 pte_t *ptep = NULL;
484
485 if (!pgd_none(*pgd)) {
486 pud_t *pud = pud_offset(pgd, addr);
487 if (!pud_none(*pud)) {
488 pmd_t *pmd = pmd_offset(pud, addr);
489 if (!pmd_none(*pmd))
490 ptep = pte_offset_map(pmd, addr);
491 }
492 }
493 return ptep;
494}
495
d6ce8626
RC
496void flush_cache_mm(struct mm_struct *mm)
497{
6d2439d9
JDA
498 /* Flushing the whole cache on each cpu takes forever on
499 rp3440, etc. So, avoid it if the mm isn't too big. */
500 if (mm_total_size(mm) < parisc_cache_flush_threshold) {
501 struct vm_area_struct *vma;
502
503 if (mm->context == mfsp(3)) {
504 for (vma = mm->mmap; vma; vma = vma->vm_next) {
505 flush_user_dcache_range_asm(vma->vm_start,
506 vma->vm_end);
507 if (vma->vm_flags & VM_EXEC)
508 flush_user_icache_range_asm(
509 vma->vm_start, vma->vm_end);
510 }
511 } else {
512 pgd_t *pgd = mm->pgd;
513
514 for (vma = mm->mmap; vma; vma = vma->vm_next) {
515 unsigned long addr;
516
517 for (addr = vma->vm_start; addr < vma->vm_end;
518 addr += PAGE_SIZE) {
519 pte_t *ptep = get_ptep(pgd, addr);
520 if (ptep != NULL) {
521 pte_t pte = *ptep;
522 __flush_cache_page(vma, addr,
523 page_to_phys(pte_page(pte)));
524 }
525 }
526 }
527 }
528 return;
529 }
530
d6ce8626
RC
531#ifdef CONFIG_SMP
532 flush_cache_all();
533#else
534 flush_cache_all_local();
535#endif
536}
537
538void
539flush_user_dcache_range(unsigned long start, unsigned long end)
540{
541 if ((end - start) < parisc_cache_flush_threshold)
542 flush_user_dcache_range_asm(start,end);
543 else
544 flush_data_cache();
545}
546
547void
548flush_user_icache_range(unsigned long start, unsigned long end)
549{
550 if ((end - start) < parisc_cache_flush_threshold)
551 flush_user_icache_range_asm(start,end);
552 else
553 flush_instruction_cache();
554}
555
d6ce8626
RC
556void flush_cache_range(struct vm_area_struct *vma,
557 unsigned long start, unsigned long end)
558{
8980a7ba 559 BUG_ON(!vma->vm_mm->context);
d6ce8626 560
6d2439d9
JDA
561 if ((end - start) < parisc_cache_flush_threshold) {
562 if (vma->vm_mm->context == mfsp(3)) {
563 flush_user_dcache_range_asm(start, end);
564 if (vma->vm_flags & VM_EXEC)
565 flush_user_icache_range_asm(start, end);
566 } else {
567 unsigned long addr;
568 pgd_t *pgd = vma->vm_mm->pgd;
569
570 for (addr = start & PAGE_MASK; addr < end;
571 addr += PAGE_SIZE) {
572 pte_t *ptep = get_ptep(pgd, addr);
573 if (ptep != NULL) {
574 pte_t pte = *ptep;
575 flush_cache_page(vma,
576 addr, pte_pfn(pte));
577 }
578 }
579 }
d6ce8626 580 } else {
6d2439d9 581#ifdef CONFIG_SMP
d6ce8626 582 flush_cache_all();
6d2439d9
JDA
583#else
584 flush_cache_all_local();
585#endif
d6ce8626
RC
586 }
587}
588
589void
590flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long pfn)
591{
592 BUG_ON(!vma->vm_mm->context);
593
b7d45818 594 flush_tlb_page(vma, vmaddr);
f311847c 595 __flush_cache_page(vma, vmaddr, page_to_phys(pfn_to_page(pfn)));
d6ce8626
RC
596
597}
cca8e902
JDA
598
599#ifdef CONFIG_PARISC_TMPALIAS
600
601void clear_user_highpage(struct page *page, unsigned long vaddr)
602{
603 void *vto;
604 unsigned long flags;
605
606 /* Clear using TMPALIAS region. The page doesn't need to
607 be flushed but the kernel mapping needs to be purged. */
608
ba969c44 609 vto = kmap_atomic(page);
cca8e902
JDA
610
611 /* The PA-RISC 2.0 Architecture book states on page F-6:
612 "Before a write-capable translation is enabled, *all*
613 non-equivalently-aliased translations must be removed
614 from the page table and purged from the TLB. (Note
615 that the caches are not required to be flushed at this
616 time.) Before any non-equivalent aliased translation
617 is re-enabled, the virtual address range for the writeable
618 page (the entire page) must be flushed from the cache,
619 and the write-capable translation removed from the page
620 table and purged from the TLB." */
621
622 purge_kernel_dcache_page_asm((unsigned long)vto);
623 purge_tlb_start(flags);
624 pdtlb_kernel(vto);
625 purge_tlb_end(flags);
626 preempt_disable();
627 clear_user_page_asm(vto, vaddr);
628 preempt_enable();
629
630 pagefault_enable(); /* kunmap_atomic(addr, KM_USER0); */
631}
632
633void copy_user_highpage(struct page *to, struct page *from,
634 unsigned long vaddr, struct vm_area_struct *vma)
635{
636 void *vfrom, *vto;
637 unsigned long flags;
638
639 /* Copy using TMPALIAS region. This has the advantage
640 that the `from' page doesn't need to be flushed. However,
641 the `to' page must be flushed in copy_user_page_asm since
642 it can be used to bring in executable code. */
643
ba969c44
ZH
644 vfrom = kmap_atomic(from);
645 vto = kmap_atomic(to);
cca8e902
JDA
646
647 purge_kernel_dcache_page_asm((unsigned long)vto);
648 purge_tlb_start(flags);
649 pdtlb_kernel(vto);
650 pdtlb_kernel(vfrom);
651 purge_tlb_end(flags);
652 preempt_disable();
653 copy_user_page_asm(vto, vfrom, vaddr);
654 flush_dcache_page_asm(__pa(vto), vaddr);
655 preempt_enable();
656
657 pagefault_enable(); /* kunmap_atomic(addr, KM_USER1); */
658 pagefault_enable(); /* kunmap_atomic(addr, KM_USER0); */
659}
660
661#endif /* CONFIG_PARISC_TMPALIAS */