aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/parisc')
-rw-r--r--arch/parisc/include/asm/cacheflush.h7
-rw-r--r--arch/parisc/include/asm/pgtable.h14
-rw-r--r--arch/parisc/kernel/cache.c109
-rw-r--r--arch/parisc/kernel/entry.S217
-rw-r--r--arch/parisc/kernel/pacache.S245
5 files changed, 260 insertions, 332 deletions
diff --git a/arch/parisc/include/asm/cacheflush.h b/arch/parisc/include/asm/cacheflush.h
index 7344e1d304af..d18328b3f938 100644
--- a/arch/parisc/include/asm/cacheflush.h
+++ b/arch/parisc/include/asm/cacheflush.h
@@ -26,8 +26,6 @@ void flush_user_dcache_range_asm(unsigned long, unsigned long);
26void flush_kernel_dcache_range_asm(unsigned long, unsigned long); 26void flush_kernel_dcache_range_asm(unsigned long, unsigned long);
27void flush_kernel_dcache_page_asm(void *); 27void flush_kernel_dcache_page_asm(void *);
28void flush_kernel_icache_page(void *); 28void flush_kernel_icache_page(void *);
29void flush_user_dcache_page(unsigned long);
30void flush_user_icache_page(unsigned long);
31void flush_user_dcache_range(unsigned long, unsigned long); 29void flush_user_dcache_range(unsigned long, unsigned long);
32void flush_user_icache_range(unsigned long, unsigned long); 30void flush_user_icache_range(unsigned long, unsigned long);
33 31
@@ -107,12 +105,15 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned
107void flush_cache_range(struct vm_area_struct *vma, 105void flush_cache_range(struct vm_area_struct *vma,
108 unsigned long start, unsigned long end); 106 unsigned long start, unsigned long end);
109 107
108/* defined in pacache.S exported in cache.c used by flush_anon_page */
109void flush_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr);
110
110#define ARCH_HAS_FLUSH_ANON_PAGE 111#define ARCH_HAS_FLUSH_ANON_PAGE
111static inline void 112static inline void
112flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr) 113flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr)
113{ 114{
114 if (PageAnon(page)) 115 if (PageAnon(page))
115 flush_user_dcache_page(vmaddr); 116 flush_dcache_page_asm(page_to_phys(page), vmaddr);
116} 117}
117 118
118#ifdef CONFIG_DEBUG_RODATA 119#ifdef CONFIG_DEBUG_RODATA
diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h
index 6f1f65d3c0ef..5d7b8ce9fdf3 100644
--- a/arch/parisc/include/asm/pgtable.h
+++ b/arch/parisc/include/asm/pgtable.h
@@ -138,8 +138,7 @@ struct vm_area_struct;
138#define _PAGE_NO_CACHE_BIT 24 /* (0x080) Uncached Page (U bit) */ 138#define _PAGE_NO_CACHE_BIT 24 /* (0x080) Uncached Page (U bit) */
139#define _PAGE_ACCESSED_BIT 23 /* (0x100) Software: Page Accessed */ 139#define _PAGE_ACCESSED_BIT 23 /* (0x100) Software: Page Accessed */
140#define _PAGE_PRESENT_BIT 22 /* (0x200) Software: translation valid */ 140#define _PAGE_PRESENT_BIT 22 /* (0x200) Software: translation valid */
141#define _PAGE_FLUSH_BIT 21 /* (0x400) Software: translation valid */ 141/* bit 21 was formerly the FLUSH bit but is now unused */
142 /* for cache flushing only */
143#define _PAGE_USER_BIT 20 /* (0x800) Software: User accessible page */ 142#define _PAGE_USER_BIT 20 /* (0x800) Software: User accessible page */
144 143
145/* N.B. The bits are defined in terms of a 32 bit word above, so the */ 144/* N.B. The bits are defined in terms of a 32 bit word above, so the */
@@ -173,7 +172,6 @@ struct vm_area_struct;
173#define _PAGE_NO_CACHE (1 << xlate_pabit(_PAGE_NO_CACHE_BIT)) 172#define _PAGE_NO_CACHE (1 << xlate_pabit(_PAGE_NO_CACHE_BIT))
174#define _PAGE_ACCESSED (1 << xlate_pabit(_PAGE_ACCESSED_BIT)) 173#define _PAGE_ACCESSED (1 << xlate_pabit(_PAGE_ACCESSED_BIT))
175#define _PAGE_PRESENT (1 << xlate_pabit(_PAGE_PRESENT_BIT)) 174#define _PAGE_PRESENT (1 << xlate_pabit(_PAGE_PRESENT_BIT))
176#define _PAGE_FLUSH (1 << xlate_pabit(_PAGE_FLUSH_BIT))
177#define _PAGE_USER (1 << xlate_pabit(_PAGE_USER_BIT)) 175#define _PAGE_USER (1 << xlate_pabit(_PAGE_USER_BIT))
178#define _PAGE_FILE (1 << xlate_pabit(_PAGE_FILE_BIT)) 176#define _PAGE_FILE (1 << xlate_pabit(_PAGE_FILE_BIT))
179 177
@@ -213,7 +211,6 @@ struct vm_area_struct;
213#define PAGE_KERNEL_RO __pgprot(_PAGE_KERNEL & ~_PAGE_WRITE) 211#define PAGE_KERNEL_RO __pgprot(_PAGE_KERNEL & ~_PAGE_WRITE)
214#define PAGE_KERNEL_UNC __pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE) 212#define PAGE_KERNEL_UNC __pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE)
215#define PAGE_GATEWAY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_GATEWAY| _PAGE_READ) 213#define PAGE_GATEWAY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_GATEWAY| _PAGE_READ)
216#define PAGE_FLUSH __pgprot(_PAGE_FLUSH)
217 214
218 215
219/* 216/*
@@ -261,7 +258,7 @@ extern unsigned long *empty_zero_page;
261 258
262#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) 259#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
263 260
264#define pte_none(x) ((pte_val(x) == 0) || (pte_val(x) & _PAGE_FLUSH)) 261#define pte_none(x) (pte_val(x) == 0)
265#define pte_present(x) (pte_val(x) & _PAGE_PRESENT) 262#define pte_present(x) (pte_val(x) & _PAGE_PRESENT)
266#define pte_clear(mm,addr,xp) do { pte_val(*(xp)) = 0; } while (0) 263#define pte_clear(mm,addr,xp) do { pte_val(*(xp)) = 0; } while (0)
267 264
@@ -444,13 +441,10 @@ struct mm_struct;
444static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) 441static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
445{ 442{
446 pte_t old_pte; 443 pte_t old_pte;
447 pte_t pte;
448 444
449 spin_lock(&pa_dbit_lock); 445 spin_lock(&pa_dbit_lock);
450 pte = old_pte = *ptep; 446 old_pte = *ptep;
451 pte_val(pte) &= ~_PAGE_PRESENT; 447 pte_clear(mm,addr,ptep);
452 pte_val(pte) |= _PAGE_FLUSH;
453 set_pte_at(mm,addr,ptep,pte);
454 spin_unlock(&pa_dbit_lock); 448 spin_unlock(&pa_dbit_lock);
455 449
456 return old_pte; 450 return old_pte;
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index d054f3da3ff5..3f11331c2775 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -27,12 +27,17 @@
27#include <asm/pgalloc.h> 27#include <asm/pgalloc.h>
28#include <asm/processor.h> 28#include <asm/processor.h>
29#include <asm/sections.h> 29#include <asm/sections.h>
30#include <asm/shmparam.h>
30 31
31int split_tlb __read_mostly; 32int split_tlb __read_mostly;
32int dcache_stride __read_mostly; 33int dcache_stride __read_mostly;
33int icache_stride __read_mostly; 34int icache_stride __read_mostly;
34EXPORT_SYMBOL(dcache_stride); 35EXPORT_SYMBOL(dcache_stride);
35 36
37void flush_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr);
38EXPORT_SYMBOL(flush_dcache_page_asm);
39void flush_icache_page_asm(unsigned long phys_addr, unsigned long vaddr);
40
36 41
37/* On some machines (e.g. ones with the Merced bus), there can be 42/* On some machines (e.g. ones with the Merced bus), there can be
38 * only a single PxTLB broadcast at a time; this must be guaranteed 43 * only a single PxTLB broadcast at a time; this must be guaranteed
@@ -259,81 +264,13 @@ void disable_sr_hashing(void)
259 panic("SpaceID hashing is still on!\n"); 264 panic("SpaceID hashing is still on!\n");
260} 265}
261 266
262/* Simple function to work out if we have an existing address translation
263 * for a user space vma. */
264static inline int translation_exists(struct vm_area_struct *vma,
265 unsigned long addr, unsigned long pfn)
266{
267 pgd_t *pgd = pgd_offset(vma->vm_mm, addr);
268 pmd_t *pmd;
269 pte_t pte;
270
271 if(pgd_none(*pgd))
272 return 0;
273
274 pmd = pmd_offset(pgd, addr);
275 if(pmd_none(*pmd) || pmd_bad(*pmd))
276 return 0;
277
278 /* We cannot take the pte lock here: flush_cache_page is usually
279 * called with pte lock already held. Whereas flush_dcache_page
280 * takes flush_dcache_mmap_lock, which is lower in the hierarchy:
281 * the vma itself is secure, but the pte might come or go racily.
282 */
283 pte = *pte_offset_map(pmd, addr);
284 /* But pte_unmap() does nothing on this architecture */
285
286 /* Filter out coincidental file entries and swap entries */
287 if (!(pte_val(pte) & (_PAGE_FLUSH|_PAGE_PRESENT)))
288 return 0;
289
290 return pte_pfn(pte) == pfn;
291}
292
293/* Private function to flush a page from the cache of a non-current
294 * process. cr25 contains the Page Directory of the current user
295 * process; we're going to hijack both it and the user space %sr3 to
296 * temporarily make the non-current process current. We have to do
297 * this because cache flushing may cause a non-access tlb miss which
298 * the handlers have to fill in from the pgd of the non-current
299 * process. */
300static inline void 267static inline void
301flush_user_cache_page_non_current(struct vm_area_struct *vma, 268__flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr,
302 unsigned long vmaddr) 269 unsigned long physaddr)
303{ 270{
304 /* save the current process space and pgd */ 271 flush_dcache_page_asm(physaddr, vmaddr);
305 unsigned long space = mfsp(3), pgd = mfctl(25); 272 if (vma->vm_flags & VM_EXEC)
306 273 flush_icache_page_asm(physaddr, vmaddr);
307 /* we don't mind taking interrupts since they may not
308 * do anything with user space, but we can't
309 * be preempted here */
310 preempt_disable();
311
312 /* make us current */
313 mtctl(__pa(vma->vm_mm->pgd), 25);
314 mtsp(vma->vm_mm->context, 3);
315
316 flush_user_dcache_page(vmaddr);
317 if(vma->vm_flags & VM_EXEC)
318 flush_user_icache_page(vmaddr);
319
320 /* put the old current process back */
321 mtsp(space, 3);
322 mtctl(pgd, 25);
323 preempt_enable();
324}
325
326
327static inline void
328__flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr)
329{
330 if (likely(vma->vm_mm->context == mfsp(3))) {
331 flush_user_dcache_page(vmaddr);
332 if (vma->vm_flags & VM_EXEC)
333 flush_user_icache_page(vmaddr);
334 } else {
335 flush_user_cache_page_non_current(vma, vmaddr);
336 }
337} 274}
338 275
339void flush_dcache_page(struct page *page) 276void flush_dcache_page(struct page *page)
@@ -342,10 +279,8 @@ void flush_dcache_page(struct page *page)
342 struct vm_area_struct *mpnt; 279 struct vm_area_struct *mpnt;
343 struct prio_tree_iter iter; 280 struct prio_tree_iter iter;
344 unsigned long offset; 281 unsigned long offset;
345 unsigned long addr; 282 unsigned long addr, old_addr = 0;
346 pgoff_t pgoff; 283 pgoff_t pgoff;
347 unsigned long pfn = page_to_pfn(page);
348
349 284
350 if (mapping && !mapping_mapped(mapping)) { 285 if (mapping && !mapping_mapped(mapping)) {
351 set_bit(PG_dcache_dirty, &page->flags); 286 set_bit(PG_dcache_dirty, &page->flags);
@@ -369,20 +304,11 @@ void flush_dcache_page(struct page *page)
369 offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT; 304 offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
370 addr = mpnt->vm_start + offset; 305 addr = mpnt->vm_start + offset;
371 306
372 /* Flush instructions produce non access tlb misses. 307 if (old_addr == 0 || (old_addr & (SHMLBA - 1)) != (addr & (SHMLBA - 1))) {
373 * On PA, we nullify these instructions rather than 308 __flush_cache_page(mpnt, addr, page_to_phys(page));
374 * taking a page fault if the pte doesn't exist. 309 if (old_addr)
375 * This is just for speed. If the page translation 310 printk(KERN_ERR "INEQUIVALENT ALIASES 0x%lx and 0x%lx in file %s\n", old_addr, addr, mpnt->vm_file ? mpnt->vm_file->f_path.dentry->d_name.name : "(null)");
376 * isn't there, there's no point exciting the 311 old_addr = addr;
377 * nadtlb handler into a nullification frenzy.
378 *
379 * Make sure we really have this page: the private
380 * mappings may cover this area but have COW'd this
381 * particular page.
382 */
383 if (translation_exists(mpnt, addr, pfn)) {
384 __flush_cache_page(mpnt, addr);
385 break;
386 } 312 }
387 } 313 }
388 flush_dcache_mmap_unlock(mapping); 314 flush_dcache_mmap_unlock(mapping);
@@ -573,7 +499,6 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long
573{ 499{
574 BUG_ON(!vma->vm_mm->context); 500 BUG_ON(!vma->vm_mm->context);
575 501
576 if (likely(translation_exists(vma, vmaddr, pfn))) 502 __flush_cache_page(vma, vmaddr, page_to_phys(pfn_to_page(pfn)));
577 __flush_cache_page(vma, vmaddr);
578 503
579} 504}
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index 6337adef30f6..e5477092a5d4 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -225,22 +225,13 @@
225#ifndef CONFIG_64BIT 225#ifndef CONFIG_64BIT
226 /* 226 /*
227 * naitlb miss interruption handler (parisc 1.1 - 32 bit) 227 * naitlb miss interruption handler (parisc 1.1 - 32 bit)
228 *
229 * Note: naitlb misses will be treated
230 * as an ordinary itlb miss for now.
231 * However, note that naitlb misses
232 * have the faulting address in the
233 * IOR/ISR.
234 */ 228 */
235 229
236 .macro naitlb_11 code 230 .macro naitlb_11 code
237 231
238 mfctl %isr,spc 232 mfctl %isr,spc
239 b itlb_miss_11 233 b naitlb_miss_11
240 mfctl %ior,va 234 mfctl %ior,va
241 /* FIXME: If user causes a naitlb miss, the priv level may not be in
242 * lower bits of va, where the itlb miss handler is expecting them
243 */
244 235
245 .align 32 236 .align 32
246 .endm 237 .endm
@@ -248,26 +239,17 @@
248 239
249 /* 240 /*
250 * naitlb miss interruption handler (parisc 2.0) 241 * naitlb miss interruption handler (parisc 2.0)
251 *
252 * Note: naitlb misses will be treated
253 * as an ordinary itlb miss for now.
254 * However, note that naitlb misses
255 * have the faulting address in the
256 * IOR/ISR.
257 */ 242 */
258 243
259 .macro naitlb_20 code 244 .macro naitlb_20 code
260 245
261 mfctl %isr,spc 246 mfctl %isr,spc
262#ifdef CONFIG_64BIT 247#ifdef CONFIG_64BIT
263 b itlb_miss_20w 248 b naitlb_miss_20w
264#else 249#else
265 b itlb_miss_20 250 b naitlb_miss_20
266#endif 251#endif
267 mfctl %ior,va 252 mfctl %ior,va
268 /* FIXME: If user causes a naitlb miss, the priv level may not be in
269 * lower bits of va, where the itlb miss handler is expecting them
270 */
271 253
272 .align 32 254 .align 32
273 .endm 255 .endm
@@ -581,7 +563,24 @@
581 copy \va,\tmp1 563 copy \va,\tmp1
582 depi 0,31,23,\tmp1 564 depi 0,31,23,\tmp1
583 cmpb,COND(<>),n \tmp,\tmp1,\fault 565 cmpb,COND(<>),n \tmp,\tmp1,\fault
584 ldi (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),\prot 566 mfctl %cr19,\tmp /* iir */
567 /* get the opcode (first six bits) into \tmp */
568 extrw,u \tmp,5,6,\tmp
569 /*
570 * Only setting the T bit prevents data cache movein
571 * Setting access rights to zero prevents instruction cache movein
572 *
573 * Note subtlety here: _PAGE_GATEWAY, _PAGE_EXEC and _PAGE_WRITE go
574 * to type field and _PAGE_READ goes to top bit of PL1
575 */
576 ldi (_PAGE_REFTRAP|_PAGE_READ|_PAGE_WRITE),\prot
577 /*
578 * so if the opcode is one (i.e. this is a memory management
579 * instruction) nullify the next load so \prot is only T.
580 * Otherwise this is a normal data operation
581 */
582 cmpiclr,= 0x01,\tmp,%r0
583 ldi (_PAGE_DIRTY|_PAGE_READ|_PAGE_WRITE),\prot
585 depd,z \prot,8,7,\prot 584 depd,z \prot,8,7,\prot
586 /* 585 /*
587 * OK, it is in the temp alias region, check whether "from" or "to". 586 * OK, it is in the temp alias region, check whether "from" or "to".
@@ -631,11 +630,7 @@ ENTRY(fault_vector_20)
631 def 13 630 def 13
632 def 14 631 def 14
633 dtlb_20 15 632 dtlb_20 15
634#if 0
635 naitlb_20 16 633 naitlb_20 16
636#else
637 def 16
638#endif
639 nadtlb_20 17 634 nadtlb_20 17
640 def 18 635 def 18
641 def 19 636 def 19
@@ -678,11 +673,7 @@ ENTRY(fault_vector_11)
678 def 13 673 def 13
679 def 14 674 def 14
680 dtlb_11 15 675 dtlb_11 15
681#if 0
682 naitlb_11 16 676 naitlb_11 16
683#else
684 def 16
685#endif
686 nadtlb_11 17 677 nadtlb_11 17
687 def 18 678 def 18
688 def 19 679 def 19
@@ -1203,7 +1194,7 @@ nadtlb_miss_20w:
1203 get_pgd spc,ptp 1194 get_pgd spc,ptp
1204 space_check spc,t0,nadtlb_fault 1195 space_check spc,t0,nadtlb_fault
1205 1196
1206 L3_ptep ptp,pte,t0,va,nadtlb_check_flush_20w 1197 L3_ptep ptp,pte,t0,va,nadtlb_check_alias_20w
1207 1198
1208 update_ptep ptp,pte,t0,t1 1199 update_ptep ptp,pte,t0,t1
1209 1200
@@ -1214,16 +1205,8 @@ nadtlb_miss_20w:
1214 rfir 1205 rfir
1215 nop 1206 nop
1216 1207
1217nadtlb_check_flush_20w: 1208nadtlb_check_alias_20w:
1218 bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate 1209 do_alias spc,t0,t1,va,pte,prot,nadtlb_emulate
1219
1220 /* Insert a "flush only" translation */
1221
1222 depdi,z 7,7,3,prot
1223 depdi 1,10,1,prot
1224
1225 /* Drop prot bits from pte and convert to page addr for idtlbt */
1226 convert_for_tlb_insert20 pte
1227 1210
1228 idtlbt pte,prot 1211 idtlbt pte,prot
1229 1212
@@ -1255,25 +1238,7 @@ dtlb_miss_11:
1255 nop 1238 nop
1256 1239
1257dtlb_check_alias_11: 1240dtlb_check_alias_11:
1258 1241 do_alias spc,t0,t1,va,pte,prot,dtlb_fault
1259 /* Check to see if fault is in the temporary alias region */
1260
1261 cmpib,<>,n 0,spc,dtlb_fault /* forward */
1262 ldil L%(TMPALIAS_MAP_START),t0
1263 copy va,t1
1264 depwi 0,31,23,t1
1265 cmpb,<>,n t0,t1,dtlb_fault /* forward */
1266 ldi (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot
1267 depw,z prot,8,7,prot
1268
1269 /*
1270 * OK, it is in the temp alias region, check whether "from" or "to".
1271 * Check "subtle" note in pacache.S re: r23/r26.
1272 */
1273
1274 extrw,u,= va,9,1,r0
1275 or,tr %r23,%r0,pte /* If "from" use "from" page */
1276 or %r26,%r0,pte /* else "to", use "to" page */
1277 1242
1278 idtlba pte,(va) 1243 idtlba pte,(va)
1279 idtlbp prot,(va) 1244 idtlbp prot,(va)
@@ -1286,7 +1251,7 @@ nadtlb_miss_11:
1286 1251
1287 space_check spc,t0,nadtlb_fault 1252 space_check spc,t0,nadtlb_fault
1288 1253
1289 L2_ptep ptp,pte,t0,va,nadtlb_check_flush_11 1254 L2_ptep ptp,pte,t0,va,nadtlb_check_alias_11
1290 1255
1291 update_ptep ptp,pte,t0,t1 1256 update_ptep ptp,pte,t0,t1
1292 1257
@@ -1304,26 +1269,11 @@ nadtlb_miss_11:
1304 rfir 1269 rfir
1305 nop 1270 nop
1306 1271
1307nadtlb_check_flush_11: 1272nadtlb_check_alias_11:
1308 bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate 1273 do_alias spc,t0,t1,va,pte,prot,nadtlb_emulate
1309
1310 /* Insert a "flush only" translation */
1311
1312 zdepi 7,7,3,prot
1313 depi 1,10,1,prot
1314 1274
1315 /* Get rid of prot bits and convert to page addr for idtlba */ 1275 idtlba pte,(va)
1316 1276 idtlbp prot,(va)
1317 depi 0,31,ASM_PFN_PTE_SHIFT,pte
1318 SHRREG pte,(ASM_PFN_PTE_SHIFT-(31-26)),pte
1319
1320 mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */
1321 mtsp spc,%sr1
1322
1323 idtlba pte,(%sr1,va)
1324 idtlbp prot,(%sr1,va)
1325
1326 mtsp t0, %sr1 /* Restore sr1 */
1327 1277
1328 rfir 1278 rfir
1329 nop 1279 nop
@@ -1359,7 +1309,7 @@ nadtlb_miss_20:
1359 1309
1360 space_check spc,t0,nadtlb_fault 1310 space_check spc,t0,nadtlb_fault
1361 1311
1362 L2_ptep ptp,pte,t0,va,nadtlb_check_flush_20 1312 L2_ptep ptp,pte,t0,va,nadtlb_check_alias_20
1363 1313
1364 update_ptep ptp,pte,t0,t1 1314 update_ptep ptp,pte,t0,t1
1365 1315
@@ -1372,21 +1322,14 @@ nadtlb_miss_20:
1372 rfir 1322 rfir
1373 nop 1323 nop
1374 1324
1375nadtlb_check_flush_20: 1325nadtlb_check_alias_20:
1376 bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate 1326 do_alias spc,t0,t1,va,pte,prot,nadtlb_emulate
1377
1378 /* Insert a "flush only" translation */
1379
1380 depdi,z 7,7,3,prot
1381 depdi 1,10,1,prot
1382
1383 /* Drop prot bits from pte and convert to page addr for idtlbt */
1384 convert_for_tlb_insert20 pte
1385 1327
1386 idtlbt pte,prot 1328 idtlbt pte,prot
1387 1329
1388 rfir 1330 rfir
1389 nop 1331 nop
1332
1390#endif 1333#endif
1391 1334
1392nadtlb_emulate: 1335nadtlb_emulate:
@@ -1484,6 +1427,36 @@ itlb_miss_20w:
1484 rfir 1427 rfir
1485 nop 1428 nop
1486 1429
1430naitlb_miss_20w:
1431
1432 /*
1433 * I miss is a little different, since we allow users to fault
1434 * on the gateway page which is in the kernel address space.
1435 */
1436
1437 space_adjust spc,va,t0
1438 get_pgd spc,ptp
1439 space_check spc,t0,naitlb_fault
1440
1441 L3_ptep ptp,pte,t0,va,naitlb_check_alias_20w
1442
1443 update_ptep ptp,pte,t0,t1
1444
1445 make_insert_tlb spc,pte,prot
1446
1447 iitlbt pte,prot
1448
1449 rfir
1450 nop
1451
1452naitlb_check_alias_20w:
1453 do_alias spc,t0,t1,va,pte,prot,naitlb_fault
1454
1455 iitlbt pte,prot
1456
1457 rfir
1458 nop
1459
1487#else 1460#else
1488 1461
1489itlb_miss_11: 1462itlb_miss_11:
@@ -1508,6 +1481,38 @@ itlb_miss_11:
1508 rfir 1481 rfir
1509 nop 1482 nop
1510 1483
1484naitlb_miss_11:
1485 get_pgd spc,ptp
1486
1487 space_check spc,t0,naitlb_fault
1488
1489 L2_ptep ptp,pte,t0,va,naitlb_check_alias_11
1490
1491 update_ptep ptp,pte,t0,t1
1492
1493 make_insert_tlb_11 spc,pte,prot
1494
1495 mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */
1496 mtsp spc,%sr1
1497
1498 iitlba pte,(%sr1,va)
1499 iitlbp prot,(%sr1,va)
1500
1501 mtsp t0, %sr1 /* Restore sr1 */
1502
1503 rfir
1504 nop
1505
1506naitlb_check_alias_11:
1507 do_alias spc,t0,t1,va,pte,prot,itlb_fault
1508
1509 iitlba pte,(%sr0, va)
1510 iitlbp prot,(%sr0, va)
1511
1512 rfir
1513 nop
1514
1515
1511itlb_miss_20: 1516itlb_miss_20:
1512 get_pgd spc,ptp 1517 get_pgd spc,ptp
1513 1518
@@ -1526,6 +1531,32 @@ itlb_miss_20:
1526 rfir 1531 rfir
1527 nop 1532 nop
1528 1533
1534naitlb_miss_20:
1535 get_pgd spc,ptp
1536
1537 space_check spc,t0,naitlb_fault
1538
1539 L2_ptep ptp,pte,t0,va,naitlb_check_alias_20
1540
1541 update_ptep ptp,pte,t0,t1
1542
1543 make_insert_tlb spc,pte,prot
1544
1545 f_extend pte,t0
1546
1547 iitlbt pte,prot
1548
1549 rfir
1550 nop
1551
1552naitlb_check_alias_20:
1553 do_alias spc,t0,t1,va,pte,prot,naitlb_fault
1554
1555 iitlbt pte,prot
1556
1557 rfir
1558 nop
1559
1529#endif 1560#endif
1530 1561
1531#ifdef CONFIG_64BIT 1562#ifdef CONFIG_64BIT
@@ -1662,6 +1693,10 @@ nadtlb_fault:
1662 b intr_save 1693 b intr_save
1663 ldi 17,%r8 1694 ldi 17,%r8
1664 1695
1696naitlb_fault:
1697 b intr_save
1698 ldi 16,%r8
1699
1665dtlb_fault: 1700dtlb_fault:
1666 b intr_save 1701 b intr_save
1667 ldi 15,%r8 1702 ldi 15,%r8
diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S
index 09b77b2553c6..a85823668cba 100644
--- a/arch/parisc/kernel/pacache.S
+++ b/arch/parisc/kernel/pacache.S
@@ -608,93 +608,131 @@ ENTRY(__clear_user_page_asm)
608 .procend 608 .procend
609ENDPROC(__clear_user_page_asm) 609ENDPROC(__clear_user_page_asm)
610 610
611ENTRY(flush_kernel_dcache_page_asm) 611ENTRY(flush_dcache_page_asm)
612 .proc 612 .proc
613 .callinfo NO_CALLS 613 .callinfo NO_CALLS
614 .entry 614 .entry
615 615
616 ldil L%(TMPALIAS_MAP_START), %r28
617#ifdef CONFIG_64BIT
618#if (TMPALIAS_MAP_START >= 0x80000000)
619 depdi 0, 31,32, %r28 /* clear any sign extension */
620 /* FIXME: page size dependend */
621#endif
622 extrd,u %r26, 56,32, %r26 /* convert phys addr to tlb insert format */
623 depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */
624 depdi 0, 63,12, %r28 /* Clear any offset bits */
625#else
626 extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */
627 depw %r25, 31,22, %r28 /* Form aliased virtual address 'to' */
628 depwi 0, 31,12, %r28 /* Clear any offset bits */
629#endif
630
631 /* Purge any old translation */
632
633 pdtlb 0(%r28)
634
616 ldil L%dcache_stride, %r1 635 ldil L%dcache_stride, %r1
617 ldw R%dcache_stride(%r1), %r23 636 ldw R%dcache_stride(%r1), %r1
618 637
619#ifdef CONFIG_64BIT 638#ifdef CONFIG_64BIT
620 depdi,z 1, 63-PAGE_SHIFT,1, %r25 639 depdi,z 1, 63-PAGE_SHIFT,1, %r25
621#else 640#else
622 depwi,z 1, 31-PAGE_SHIFT,1, %r25 641 depwi,z 1, 31-PAGE_SHIFT,1, %r25
623#endif 642#endif
624 add %r26, %r25, %r25 643 add %r28, %r25, %r25
625 sub %r25, %r23, %r25 644 sub %r25, %r1, %r25
626 645
627 646
6281: fdc,m %r23(%r26) 6471: fdc,m %r1(%r28)
629 fdc,m %r23(%r26) 648 fdc,m %r1(%r28)
630 fdc,m %r23(%r26) 649 fdc,m %r1(%r28)
631 fdc,m %r23(%r26) 650 fdc,m %r1(%r28)
632 fdc,m %r23(%r26) 651 fdc,m %r1(%r28)
633 fdc,m %r23(%r26) 652 fdc,m %r1(%r28)
634 fdc,m %r23(%r26) 653 fdc,m %r1(%r28)
635 fdc,m %r23(%r26) 654 fdc,m %r1(%r28)
636 fdc,m %r23(%r26) 655 fdc,m %r1(%r28)
637 fdc,m %r23(%r26) 656 fdc,m %r1(%r28)
638 fdc,m %r23(%r26) 657 fdc,m %r1(%r28)
639 fdc,m %r23(%r26) 658 fdc,m %r1(%r28)
640 fdc,m %r23(%r26) 659 fdc,m %r1(%r28)
641 fdc,m %r23(%r26) 660 fdc,m %r1(%r28)
642 fdc,m %r23(%r26) 661 fdc,m %r1(%r28)
643 cmpb,COND(<<) %r26, %r25,1b 662 cmpb,COND(<<) %r28, %r25,1b
644 fdc,m %r23(%r26) 663 fdc,m %r1(%r28)
645 664
646 sync 665 sync
647 bv %r0(%r2) 666 bv %r0(%r2)
648 nop 667 pdtlb (%r25)
649 .exit 668 .exit
650 669
651 .procend 670 .procend
652ENDPROC(flush_kernel_dcache_page_asm) 671ENDPROC(flush_dcache_page_asm)
653 672
654ENTRY(flush_user_dcache_page) 673ENTRY(flush_icache_page_asm)
655 .proc 674 .proc
656 .callinfo NO_CALLS 675 .callinfo NO_CALLS
657 .entry 676 .entry
658 677
659 ldil L%dcache_stride, %r1 678 ldil L%(TMPALIAS_MAP_START), %r28
660 ldw R%dcache_stride(%r1), %r23
661
662#ifdef CONFIG_64BIT 679#ifdef CONFIG_64BIT
663 depdi,z 1,63-PAGE_SHIFT,1, %r25 680#if (TMPALIAS_MAP_START >= 0x80000000)
681 depdi 0, 31,32, %r28 /* clear any sign extension */
682 /* FIXME: page size dependend */
683#endif
684 extrd,u %r26, 56,32, %r26 /* convert phys addr to tlb insert format */
685 depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */
686 depdi 0, 63,12, %r28 /* Clear any offset bits */
664#else 687#else
665 depwi,z 1,31-PAGE_SHIFT,1, %r25 688 extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */
689 depw %r25, 31,22, %r28 /* Form aliased virtual address 'to' */
690 depwi 0, 31,12, %r28 /* Clear any offset bits */
666#endif 691#endif
667 add %r26, %r25, %r25
668 sub %r25, %r23, %r25
669 692
693 /* Purge any old translation */
670 694
6711: fdc,m %r23(%sr3, %r26) 695 pitlb (%sr0,%r28)
672 fdc,m %r23(%sr3, %r26) 696
673 fdc,m %r23(%sr3, %r26) 697 ldil L%icache_stride, %r1
674 fdc,m %r23(%sr3, %r26) 698 ldw R%icache_stride(%r1), %r1
675 fdc,m %r23(%sr3, %r26) 699
676 fdc,m %r23(%sr3, %r26) 700#ifdef CONFIG_64BIT
677 fdc,m %r23(%sr3, %r26) 701 depdi,z 1, 63-PAGE_SHIFT,1, %r25
678 fdc,m %r23(%sr3, %r26) 702#else
679 fdc,m %r23(%sr3, %r26) 703 depwi,z 1, 31-PAGE_SHIFT,1, %r25
680 fdc,m %r23(%sr3, %r26) 704#endif
681 fdc,m %r23(%sr3, %r26) 705 add %r28, %r25, %r25
682 fdc,m %r23(%sr3, %r26) 706 sub %r25, %r1, %r25
683 fdc,m %r23(%sr3, %r26) 707
684 fdc,m %r23(%sr3, %r26) 708
685 fdc,m %r23(%sr3, %r26) 7091: fic,m %r1(%r28)
686 cmpb,COND(<<) %r26, %r25,1b 710 fic,m %r1(%r28)
687 fdc,m %r23(%sr3, %r26) 711 fic,m %r1(%r28)
712 fic,m %r1(%r28)
713 fic,m %r1(%r28)
714 fic,m %r1(%r28)
715 fic,m %r1(%r28)
716 fic,m %r1(%r28)
717 fic,m %r1(%r28)
718 fic,m %r1(%r28)
719 fic,m %r1(%r28)
720 fic,m %r1(%r28)
721 fic,m %r1(%r28)
722 fic,m %r1(%r28)
723 fic,m %r1(%r28)
724 cmpb,COND(<<) %r28, %r25,1b
725 fic,m %r1(%r28)
688 726
689 sync 727 sync
690 bv %r0(%r2) 728 bv %r0(%r2)
691 nop 729 pitlb (%sr0,%r25)
692 .exit 730 .exit
693 731
694 .procend 732 .procend
695ENDPROC(flush_user_dcache_page) 733ENDPROC(flush_icache_page_asm)
696 734
697ENTRY(flush_user_icache_page) 735ENTRY(flush_kernel_dcache_page_asm)
698 .proc 736 .proc
699 .callinfo NO_CALLS 737 .callinfo NO_CALLS
700 .entry 738 .entry
@@ -711,23 +749,23 @@ ENTRY(flush_user_icache_page)
711 sub %r25, %r23, %r25 749 sub %r25, %r23, %r25
712 750
713 751
7141: fic,m %r23(%sr3, %r26) 7521: fdc,m %r23(%r26)
715 fic,m %r23(%sr3, %r26) 753 fdc,m %r23(%r26)
716 fic,m %r23(%sr3, %r26) 754 fdc,m %r23(%r26)
717 fic,m %r23(%sr3, %r26) 755 fdc,m %r23(%r26)
718 fic,m %r23(%sr3, %r26) 756 fdc,m %r23(%r26)
719 fic,m %r23(%sr3, %r26) 757 fdc,m %r23(%r26)
720 fic,m %r23(%sr3, %r26) 758 fdc,m %r23(%r26)
721 fic,m %r23(%sr3, %r26) 759 fdc,m %r23(%r26)
722 fic,m %r23(%sr3, %r26) 760 fdc,m %r23(%r26)
723 fic,m %r23(%sr3, %r26) 761 fdc,m %r23(%r26)
724 fic,m %r23(%sr3, %r26) 762 fdc,m %r23(%r26)
725 fic,m %r23(%sr3, %r26) 763 fdc,m %r23(%r26)
726 fic,m %r23(%sr3, %r26) 764 fdc,m %r23(%r26)
727 fic,m %r23(%sr3, %r26) 765 fdc,m %r23(%r26)
728 fic,m %r23(%sr3, %r26) 766 fdc,m %r23(%r26)
729 cmpb,COND(<<) %r26, %r25,1b 767 cmpb,COND(<<) %r26, %r25,1b
730 fic,m %r23(%sr3, %r26) 768 fdc,m %r23(%r26)
731 769
732 sync 770 sync
733 bv %r0(%r2) 771 bv %r0(%r2)
@@ -735,8 +773,7 @@ ENTRY(flush_user_icache_page)
735 .exit 773 .exit
736 774
737 .procend 775 .procend
738ENDPROC(flush_user_icache_page) 776ENDPROC(flush_kernel_dcache_page_asm)
739
740 777
741ENTRY(purge_kernel_dcache_page) 778ENTRY(purge_kernel_dcache_page)
742 .proc 779 .proc
@@ -780,69 +817,6 @@ ENTRY(purge_kernel_dcache_page)
780 .procend 817 .procend
781ENDPROC(purge_kernel_dcache_page) 818ENDPROC(purge_kernel_dcache_page)
782 819
783#if 0
784 /* Currently not used, but it still is a possible alternate
785 * solution.
786 */
787
788ENTRY(flush_alias_page)
789 .proc
790 .callinfo NO_CALLS
791 .entry
792
793 tophys_r1 %r26
794
795 ldil L%(TMPALIAS_MAP_START), %r28
796#ifdef CONFIG_64BIT
797 extrd,u %r26, 56,32, %r26 /* convert phys addr to tlb insert format */
798 depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */
799 depdi 0, 63,12, %r28 /* Clear any offset bits */
800#else
801 extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */
802 depw %r25, 31,22, %r28 /* Form aliased virtual address 'to' */
803 depwi 0, 31,12, %r28 /* Clear any offset bits */
804#endif
805
806 /* Purge any old translation */
807
808 pdtlb 0(%r28)
809
810 ldil L%dcache_stride, %r1
811 ldw R%dcache_stride(%r1), %r23
812
813#ifdef CONFIG_64BIT
814 depdi,z 1, 63-PAGE_SHIFT,1, %r29
815#else
816 depwi,z 1, 31-PAGE_SHIFT,1, %r29
817#endif
818 add %r28, %r29, %r29
819 sub %r29, %r23, %r29
820
8211: fdc,m %r23(%r28)
822 fdc,m %r23(%r28)
823 fdc,m %r23(%r28)
824 fdc,m %r23(%r28)
825 fdc,m %r23(%r28)
826 fdc,m %r23(%r28)
827 fdc,m %r23(%r28)
828 fdc,m %r23(%r28)
829 fdc,m %r23(%r28)
830 fdc,m %r23(%r28)
831 fdc,m %r23(%r28)
832 fdc,m %r23(%r28)
833 fdc,m %r23(%r28)
834 fdc,m %r23(%r28)
835 fdc,m %r23(%r28)
836 cmpb,COND(<<) %r28, %r29, 1b
837 fdc,m %r23(%r28)
838
839 sync
840 bv %r0(%r2)
841 nop
842 .exit
843
844 .procend
845#endif
846 820
847 .export flush_user_dcache_range_asm 821 .export flush_user_dcache_range_asm
848 822
@@ -865,7 +839,6 @@ flush_user_dcache_range_asm:
865 .exit 839 .exit
866 840
867 .procend 841 .procend
868ENDPROC(flush_alias_page)
869 842
870ENTRY(flush_kernel_dcache_range_asm) 843ENTRY(flush_kernel_dcache_range_asm)
871 .proc 844 .proc