Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

parisc: Fix some PTE/TLB race conditions and optimize __flush_tlb_range based on timing results

The increased use of pdtlb/pitlb instructions seemed to increase the
frequency of random segmentation faults building packages. Further, we
had a number of cases where TLB inserts would repeatedly fail and all
forward progress would stop. The Haskell ghc package caused a lot of
trouble in this area. The final indication of a race in pte handling was
this syslog entry on sibaris (C8000):

swap_free: Unused swap offset entry 00000004
BUG: Bad page map in process mysqld pte:00000100 pmd:019bbec5
addr:00000000ec464000 vm_flags:00100073 anon_vma:0000000221023828 mapping: (null) index:ec464
CPU: 1 PID: 9176 Comm: mysqld Not tainted 4.0.0-2-parisc64-smp #1 Debian 4.0.5-1
Backtrace:
[<0000000040173eb0>] show_stack+0x20/0x38
[<0000000040444424>] dump_stack+0x9c/0x110
[<00000000402a0d38>] print_bad_pte+0x1a8/0x278
[<00000000402a28b8>] unmap_single_vma+0x3d8/0x770
[<00000000402a4090>] zap_page_range+0xf0/0x198
[<00000000402ba2a4>] SyS_madvise+0x404/0x8c0

Note that the pte value is 0 except for the accessed bit 0x100. This bit
shouldn't be set without the present bit.

It should be noted that the madvise system call is probably a trigger for many
of the random segmentation faults.

In looking at the kernel code, I found the following problems:

1) The pte_clear define didn't take TLB lock when clearing a pte.
2) We didn't test pte present bit inside lock in exception support.
3) The pte and tlb locks needed to merged in order to ensure consistency
between page table and TLB. This also has the effect of serializing TLB
broadcasts on SMP systems.

The attached change implements the above and a few other tweaks to try
to improve performance. Based on the timing code, TLB purges are very
slow (e.g., ~ 209 cycles per page on rp3440). Thus, I think it
beneficial to test the split_tlb variable to avoid duplicate purges.
Probably, all PA 2.0 machines have combined TLBs.

I dropped using __flush_tlb_range in flush_tlb_mm as I realized all
applications and most threads have a stack size that is too large to
make this useful. I added some comments to this effect.

Since implementing 1 through 3, I haven't had any random segmentation
faults on mx3210 (rp3440) in about one week of building code and running
as a Debian buildd.

Signed-off-by: John David Anglin <dave.anglin@bell.net>
Cc: stable@vger.kernel.org # v3.18+
Signed-off-by: Helge Deller <deller@gmx.de>

authored by

John David Anglin and committed by
Helge Deller
01ab6057 cb908ed3

+212 -168
+37 -18
arch/parisc/include/asm/pgtable.h
··· 16 16 #include <asm/processor.h> 17 17 #include <asm/cache.h> 18 18 19 - extern spinlock_t pa_dbit_lock; 19 + extern spinlock_t pa_tlb_lock; 20 20 21 21 /* 22 22 * kern_addr_valid(ADDR) tests if ADDR is pointing to valid kernel ··· 33 33 */ 34 34 #define kern_addr_valid(addr) (1) 35 35 36 + /* Purge data and instruction TLB entries. Must be called holding 37 + * the pa_tlb_lock. The TLB purge instructions are slow on SMP 38 + * machines since the purge must be broadcast to all CPUs. 39 + */ 40 + 41 + static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr) 42 + { 43 + mtsp(mm->context, 1); 44 + pdtlb(addr); 45 + if (unlikely(split_tlb)) 46 + pitlb(addr); 47 + } 48 + 36 49 /* Certain architectures need to do special things when PTEs 37 50 * within a page table are directly modified. Thus, the following 38 51 * hook is made available. ··· 55 42 *(pteptr) = (pteval); \ 56 43 } while(0) 57 44 58 - extern void purge_tlb_entries(struct mm_struct *, unsigned long); 45 + #define pte_inserted(x) \ 46 + ((pte_val(x) & (_PAGE_PRESENT|_PAGE_ACCESSED)) \ 47 + == (_PAGE_PRESENT|_PAGE_ACCESSED)) 59 48 60 - #define set_pte_at(mm, addr, ptep, pteval) \ 61 - do { \ 49 + #define set_pte_at(mm, addr, ptep, pteval) \ 50 + do { \ 51 + pte_t old_pte; \ 62 52 unsigned long flags; \ 63 - spin_lock_irqsave(&pa_dbit_lock, flags); \ 64 - set_pte(ptep, pteval); \ 65 - purge_tlb_entries(mm, addr); \ 66 - spin_unlock_irqrestore(&pa_dbit_lock, flags); \ 53 + spin_lock_irqsave(&pa_tlb_lock, flags); \ 54 + old_pte = *ptep; \ 55 + set_pte(ptep, pteval); \ 56 + if (pte_inserted(old_pte)) \ 57 + purge_tlb_entries(mm, addr); \ 58 + spin_unlock_irqrestore(&pa_tlb_lock, flags); \ 67 59 } while (0) 68 60 69 61 #endif /* !__ASSEMBLY__ */ ··· 286 268 287 269 #define pte_none(x) (pte_val(x) == 0) 288 270 #define pte_present(x) (pte_val(x) & _PAGE_PRESENT) 289 - #define pte_clear(mm,addr,xp) do { pte_val(*(xp)) = 0; } while (0) 271 + #define pte_clear(mm, addr, xp) set_pte_at(mm, addr, xp, __pte(0)) 290 272 291 273 #define pmd_flag(x) (pmd_val(x) & PxD_FLAG_MASK) 292 274 #define pmd_address(x) ((unsigned long)(pmd_val(x) &~ PxD_FLAG_MASK) << PxD_VALUE_SHIFT) ··· 453 435 if (!pte_young(*ptep)) 454 436 return 0; 455 437 456 - spin_lock_irqsave(&pa_dbit_lock, flags); 438 + spin_lock_irqsave(&pa_tlb_lock, flags); 457 439 pte = *ptep; 458 440 if (!pte_young(pte)) { 459 - spin_unlock_irqrestore(&pa_dbit_lock, flags); 441 + spin_unlock_irqrestore(&pa_tlb_lock, flags); 460 442 return 0; 461 443 } 462 444 set_pte(ptep, pte_mkold(pte)); 463 445 purge_tlb_entries(vma->vm_mm, addr); 464 - spin_unlock_irqrestore(&pa_dbit_lock, flags); 446 + spin_unlock_irqrestore(&pa_tlb_lock, flags); 465 447 return 1; 466 448 } 467 449 ··· 471 453 pte_t old_pte; 472 454 unsigned long flags; 473 455 474 - spin_lock_irqsave(&pa_dbit_lock, flags); 456 + spin_lock_irqsave(&pa_tlb_lock, flags); 475 457 old_pte = *ptep; 476 - pte_clear(mm,addr,ptep); 477 - purge_tlb_entries(mm, addr); 478 - spin_unlock_irqrestore(&pa_dbit_lock, flags); 458 + set_pte(ptep, __pte(0)); 459 + if (pte_inserted(old_pte)) 460 + purge_tlb_entries(mm, addr); 461 + spin_unlock_irqrestore(&pa_tlb_lock, flags); 479 462 480 463 return old_pte; 481 464 } ··· 484 465 static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) 485 466 { 486 467 unsigned long flags; 487 - spin_lock_irqsave(&pa_dbit_lock, flags); 468 + spin_lock_irqsave(&pa_tlb_lock, flags); 488 469 set_pte(ptep, pte_wrprotect(*ptep)); 489 470 purge_tlb_entries(mm, addr); 490 - spin_unlock_irqrestore(&pa_dbit_lock, flags); 471 + spin_unlock_irqrestore(&pa_tlb_lock, flags); 491 472 } 492 473 493 474 #define pte_same(A,B) (pte_val(A) == pte_val(B))
+29 -24
arch/parisc/include/asm/tlbflush.h
··· 13 13 * active at any one time on the Merced bus. This tlb purge 14 14 * synchronisation is fairly lightweight and harmless so we activate 15 15 * it on all systems not just the N class. 16 + 17 + * It is also used to ensure PTE updates are atomic and consistent 18 + * with the TLB. 16 19 */ 17 20 extern spinlock_t pa_tlb_lock; 18 21 ··· 27 24 28 25 #define smp_flush_tlb_all() flush_tlb_all() 29 26 27 + int __flush_tlb_range(unsigned long sid, 28 + unsigned long start, unsigned long end); 29 + 30 + #define flush_tlb_range(vma, start, end) \ 31 + __flush_tlb_range((vma)->vm_mm->context, start, end) 32 + 33 + #define flush_tlb_kernel_range(start, end) \ 34 + __flush_tlb_range(0, start, end) 35 + 30 36 /* 31 37 * flush_tlb_mm() 32 38 * 33 - * XXX This code is NOT valid for HP-UX compatibility processes, 34 - * (although it will probably work 99% of the time). HP-UX 35 - * processes are free to play with the space id's and save them 36 - * over long periods of time, etc. so we have to preserve the 37 - * space and just flush the entire tlb. We need to check the 38 - * personality in order to do that, but the personality is not 39 - * currently being set correctly. 40 - * 41 - * Of course, Linux processes could do the same thing, but 42 - * we don't support that (and the compilers, dynamic linker, 43 - * etc. do not do that). 39 + * The code to switch to a new context is NOT valid for processes 40 + * which play with the space id's. Thus, we have to preserve the 41 + * space and just flush the entire tlb. However, the compilers, 42 + * dynamic linker, etc, do not manipulate space id's, so there 43 + * could be a significant performance benefit in switching contexts 44 + * and not flushing the whole tlb. 44 45 */ 45 46 46 47 static inline void flush_tlb_mm(struct mm_struct *mm) ··· 52 45 BUG_ON(mm == &init_mm); /* Should never happen */ 53 46 54 47 #if 1 || defined(CONFIG_SMP) 48 + /* Except for very small threads, flushing the whole TLB is 49 + * faster than using __flush_tlb_range. The pdtlb and pitlb 50 + * instructions are very slow because of the TLB broadcast. 51 + * It might be faster to do local range flushes on all CPUs 52 + * on PA 2.0 systems. 53 + */ 55 54 flush_tlb_all(); 56 55 #else 57 56 /* FIXME: currently broken, causing space id and protection ids 58 - * to go out of sync, resulting in faults on userspace accesses. 57 + * to go out of sync, resulting in faults on userspace accesses. 58 + * This approach needs further investigation since running many 59 + * small applications (e.g., GCC testsuite) is faster on HP-UX. 59 60 */ 60 61 if (mm) { 61 62 if (mm->context != 0) ··· 80 65 { 81 66 unsigned long flags, sid; 82 67 83 - /* For one page, it's not worth testing the split_tlb variable */ 84 - 85 - mb(); 86 68 sid = vma->vm_mm->context; 87 69 purge_tlb_start(flags); 88 70 mtsp(sid, 1); 89 71 pdtlb(addr); 90 - pitlb(addr); 72 + if (unlikely(split_tlb)) 73 + pitlb(addr); 91 74 purge_tlb_end(flags); 92 75 } 93 - 94 - void __flush_tlb_range(unsigned long sid, 95 - unsigned long start, unsigned long end); 96 - 97 - #define flush_tlb_range(vma,start,end) __flush_tlb_range((vma)->vm_mm->context,start,end) 98 - 99 - #define flush_tlb_kernel_range(start, end) __flush_tlb_range(0,start,end) 100 - 101 76 #endif
+67 -38
arch/parisc/kernel/cache.c
··· 342 342 EXPORT_SYMBOL(flush_kernel_icache_range_asm); 343 343 344 344 #define FLUSH_THRESHOLD 0x80000 /* 0.5MB */ 345 - int parisc_cache_flush_threshold __read_mostly = FLUSH_THRESHOLD; 345 + static unsigned long parisc_cache_flush_threshold __read_mostly = FLUSH_THRESHOLD; 346 + 347 + #define FLUSH_TLB_THRESHOLD (2*1024*1024) /* 2MB initial TLB threshold */ 348 + static unsigned long parisc_tlb_flush_threshold __read_mostly = FLUSH_TLB_THRESHOLD; 346 349 347 350 void __init parisc_setup_cache_timing(void) 348 351 { 349 352 unsigned long rangetime, alltime; 350 - unsigned long size; 353 + unsigned long size, start; 351 354 352 355 alltime = mfctl(16); 353 356 flush_data_cache(); ··· 367 364 /* Racy, but if we see an intermediate value, it's ok too... */ 368 365 parisc_cache_flush_threshold = size * alltime / rangetime; 369 366 370 - parisc_cache_flush_threshold = (parisc_cache_flush_threshold + L1_CACHE_BYTES - 1) &~ (L1_CACHE_BYTES - 1); 367 + parisc_cache_flush_threshold = L1_CACHE_ALIGN(parisc_cache_flush_threshold); 371 368 if (!parisc_cache_flush_threshold) 372 369 parisc_cache_flush_threshold = FLUSH_THRESHOLD; 373 370 374 371 if (parisc_cache_flush_threshold > cache_info.dc_size) 375 372 parisc_cache_flush_threshold = cache_info.dc_size; 376 373 377 - printk(KERN_INFO "Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus()); 374 + printk(KERN_INFO "Setting cache flush threshold to %lu kB\n", 375 + parisc_cache_flush_threshold/1024); 376 + 377 + /* calculate TLB flush threshold */ 378 + 379 + alltime = mfctl(16); 380 + flush_tlb_all(); 381 + alltime = mfctl(16) - alltime; 382 + 383 + size = PAGE_SIZE; 384 + start = (unsigned long) _text; 385 + rangetime = mfctl(16); 386 + while (start < (unsigned long) _end) { 387 + flush_tlb_kernel_range(start, start + PAGE_SIZE); 388 + start += PAGE_SIZE; 389 + size += PAGE_SIZE; 390 + } 391 + rangetime = mfctl(16) - rangetime; 392 + 393 + printk(KERN_DEBUG "Whole TLB flush %lu cycles, flushing %lu bytes %lu cycles\n", 394 + alltime, size, rangetime); 395 + 396 + parisc_tlb_flush_threshold = size * alltime / rangetime; 397 + parisc_tlb_flush_threshold *= num_online_cpus(); 398 + parisc_tlb_flush_threshold = PAGE_ALIGN(parisc_tlb_flush_threshold); 399 + if (!parisc_tlb_flush_threshold) 400 + parisc_tlb_flush_threshold = FLUSH_TLB_THRESHOLD; 401 + 402 + printk(KERN_INFO "Setting TLB flush threshold to %lu kB\n", 403 + parisc_tlb_flush_threshold/1024); 378 404 } 379 405 380 406 extern void purge_kernel_dcache_page_asm(unsigned long); ··· 435 403 } 436 404 EXPORT_SYMBOL(copy_user_page); 437 405 438 - void purge_tlb_entries(struct mm_struct *mm, unsigned long addr) 406 + /* __flush_tlb_range() 407 + * 408 + * returns 1 if all TLBs were flushed. 409 + */ 410 + int __flush_tlb_range(unsigned long sid, unsigned long start, 411 + unsigned long end) 439 412 { 440 - unsigned long flags; 413 + unsigned long flags, size; 441 414 442 - /* Note: purge_tlb_entries can be called at startup with 443 - no context. */ 444 - 445 - purge_tlb_start(flags); 446 - mtsp(mm->context, 1); 447 - pdtlb(addr); 448 - pitlb(addr); 449 - purge_tlb_end(flags); 450 - } 451 - EXPORT_SYMBOL(purge_tlb_entries); 452 - 453 - void __flush_tlb_range(unsigned long sid, unsigned long start, 454 - unsigned long end) 455 - { 456 - unsigned long npages; 457 - 458 - npages = ((end - (start & PAGE_MASK)) + (PAGE_SIZE - 1)) >> PAGE_SHIFT; 459 - if (npages >= 512) /* 2MB of space: arbitrary, should be tuned */ 415 + size = (end - start); 416 + if (size >= parisc_tlb_flush_threshold) { 460 417 flush_tlb_all(); 461 - else { 462 - unsigned long flags; 418 + return 1; 419 + } 463 420 421 + /* Purge TLB entries for small ranges using the pdtlb and 422 + pitlb instructions. These instructions execute locally 423 + but cause a purge request to be broadcast to other TLBs. */ 424 + if (likely(!split_tlb)) { 425 + while (start < end) { 426 + purge_tlb_start(flags); 427 + mtsp(sid, 1); 428 + pdtlb(start); 429 + purge_tlb_end(flags); 430 + start += PAGE_SIZE; 431 + } 432 + return 0; 433 + } 434 + 435 + /* split TLB case */ 436 + while (start < end) { 464 437 purge_tlb_start(flags); 465 438 mtsp(sid, 1); 466 - if (split_tlb) { 467 - while (npages--) { 468 - pdtlb(start); 469 - pitlb(start); 470 - start += PAGE_SIZE; 471 - } 472 - } else { 473 - while (npages--) { 474 - pdtlb(start); 475 - start += PAGE_SIZE; 476 - } 477 - } 439 + pdtlb(start); 440 + pitlb(start); 478 441 purge_tlb_end(flags); 442 + start += PAGE_SIZE; 479 443 } 444 + return 0; 480 445 } 481 446 482 447 static void cacheflush_h_tmp_function(void *dummy)
+79 -84
arch/parisc/kernel/entry.S
··· 45 45 .level 2.0 46 46 #endif 47 47 48 - .import pa_dbit_lock,data 48 + .import pa_tlb_lock,data 49 49 50 50 /* space_to_prot macro creates a prot id from a space id */ 51 51 ··· 420 420 SHLREG %r9,PxD_VALUE_SHIFT,\pmd 421 421 extru \va,31-PAGE_SHIFT,ASM_BITS_PER_PTE,\index 422 422 dep %r0,31,PAGE_SHIFT,\pmd /* clear offset */ 423 - shladd \index,BITS_PER_PTE_ENTRY,\pmd,\pmd 424 - LDREG %r0(\pmd),\pte /* pmd is now pte */ 423 + shladd \index,BITS_PER_PTE_ENTRY,\pmd,\pmd /* pmd is now pte */ 424 + LDREG %r0(\pmd),\pte 425 425 bb,>=,n \pte,_PAGE_PRESENT_BIT,\fault 426 426 .endm 427 427 ··· 453 453 L2_ptep \pgd,\pte,\index,\va,\fault 454 454 .endm 455 455 456 - /* Acquire pa_dbit_lock lock. */ 457 - .macro dbit_lock spc,tmp,tmp1 456 + /* Acquire pa_tlb_lock lock and recheck page is still present. */ 457 + .macro tlb_lock spc,ptp,pte,tmp,tmp1,fault 458 458 #ifdef CONFIG_SMP 459 459 cmpib,COND(=),n 0,\spc,2f 460 - load32 PA(pa_dbit_lock),\tmp 460 + load32 PA(pa_tlb_lock),\tmp 461 461 1: LDCW 0(\tmp),\tmp1 462 462 cmpib,COND(=) 0,\tmp1,1b 463 463 nop 464 + LDREG 0(\ptp),\pte 465 + bb,<,n \pte,_PAGE_PRESENT_BIT,2f 466 + b \fault 467 + stw \spc,0(\tmp) 464 468 2: 465 469 #endif 466 470 .endm 467 471 468 - /* Release pa_dbit_lock lock without reloading lock address. */ 469 - .macro dbit_unlock0 spc,tmp 472 + /* Release pa_tlb_lock lock without reloading lock address. */ 473 + .macro tlb_unlock0 spc,tmp 470 474 #ifdef CONFIG_SMP 471 475 or,COND(=) %r0,\spc,%r0 472 476 stw \spc,0(\tmp) 473 477 #endif 474 478 .endm 475 479 476 - /* Release pa_dbit_lock lock. */ 477 - .macro dbit_unlock1 spc,tmp 480 + /* Release pa_tlb_lock lock. */ 481 + .macro tlb_unlock1 spc,tmp 478 482 #ifdef CONFIG_SMP 479 - load32 PA(pa_dbit_lock),\tmp 480 - dbit_unlock0 \spc,\tmp 483 + load32 PA(pa_tlb_lock),\tmp 484 + tlb_unlock0 \spc,\tmp 481 485 #endif 482 486 .endm 483 487 484 488 /* Set the _PAGE_ACCESSED bit of the PTE. Be clever and 485 489 * don't needlessly dirty the cache line if it was already set */ 486 - .macro update_ptep spc,ptep,pte,tmp,tmp1 487 - #ifdef CONFIG_SMP 488 - or,COND(=) %r0,\spc,%r0 489 - LDREG 0(\ptep),\pte 490 - #endif 490 + .macro update_accessed ptp,pte,tmp,tmp1 491 491 ldi _PAGE_ACCESSED,\tmp1 492 492 or \tmp1,\pte,\tmp 493 493 and,COND(<>) \tmp1,\pte,%r0 494 - STREG \tmp,0(\ptep) 494 + STREG \tmp,0(\ptp) 495 495 .endm 496 496 497 497 /* Set the dirty bit (and accessed bit). No need to be 498 498 * clever, this is only used from the dirty fault */ 499 - .macro update_dirty spc,ptep,pte,tmp 500 - #ifdef CONFIG_SMP 501 - or,COND(=) %r0,\spc,%r0 502 - LDREG 0(\ptep),\pte 503 - #endif 499 + .macro update_dirty ptp,pte,tmp 504 500 ldi _PAGE_ACCESSED|_PAGE_DIRTY,\tmp 505 501 or \tmp,\pte,\pte 506 - STREG \pte,0(\ptep) 502 + STREG \pte,0(\ptp) 507 503 .endm 508 504 509 505 /* bitshift difference between a PFN (based on kernel's PAGE_SIZE) ··· 1144 1148 1145 1149 L3_ptep ptp,pte,t0,va,dtlb_check_alias_20w 1146 1150 1147 - dbit_lock spc,t0,t1 1148 - update_ptep spc,ptp,pte,t0,t1 1151 + tlb_lock spc,ptp,pte,t0,t1,dtlb_check_alias_20w 1152 + update_accessed ptp,pte,t0,t1 1149 1153 1150 1154 make_insert_tlb spc,pte,prot 1151 1155 1152 1156 idtlbt pte,prot 1153 - dbit_unlock1 spc,t0 1154 1157 1158 + tlb_unlock1 spc,t0 1155 1159 rfir 1156 1160 nop 1157 1161 ··· 1170 1174 1171 1175 L3_ptep ptp,pte,t0,va,nadtlb_check_alias_20w 1172 1176 1173 - dbit_lock spc,t0,t1 1174 - update_ptep spc,ptp,pte,t0,t1 1177 + tlb_lock spc,ptp,pte,t0,t1,nadtlb_check_alias_20w 1178 + update_accessed ptp,pte,t0,t1 1175 1179 1176 1180 make_insert_tlb spc,pte,prot 1177 1181 1178 1182 idtlbt pte,prot 1179 - dbit_unlock1 spc,t0 1180 1183 1184 + tlb_unlock1 spc,t0 1181 1185 rfir 1182 1186 nop 1183 1187 ··· 1198 1202 1199 1203 L2_ptep ptp,pte,t0,va,dtlb_check_alias_11 1200 1204 1201 - dbit_lock spc,t0,t1 1202 - update_ptep spc,ptp,pte,t0,t1 1205 + tlb_lock spc,ptp,pte,t0,t1,dtlb_check_alias_11 1206 + update_accessed ptp,pte,t0,t1 1203 1207 1204 1208 make_insert_tlb_11 spc,pte,prot 1205 1209 1206 - mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ 1210 + mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */ 1207 1211 mtsp spc,%sr1 1208 1212 1209 1213 idtlba pte,(%sr1,va) 1210 1214 idtlbp prot,(%sr1,va) 1211 1215 1212 - mtsp t0, %sr1 /* Restore sr1 */ 1213 - dbit_unlock1 spc,t0 1216 + mtsp t1, %sr1 /* Restore sr1 */ 1214 1217 1218 + tlb_unlock1 spc,t0 1215 1219 rfir 1216 1220 nop 1217 1221 ··· 1231 1235 1232 1236 L2_ptep ptp,pte,t0,va,nadtlb_check_alias_11 1233 1237 1234 - dbit_lock spc,t0,t1 1235 - update_ptep spc,ptp,pte,t0,t1 1238 + tlb_lock spc,ptp,pte,t0,t1,nadtlb_check_alias_11 1239 + update_accessed ptp,pte,t0,t1 1236 1240 1237 1241 make_insert_tlb_11 spc,pte,prot 1238 1242 1239 - 1240 - mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ 1243 + mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */ 1241 1244 mtsp spc,%sr1 1242 1245 1243 1246 idtlba pte,(%sr1,va) 1244 1247 idtlbp prot,(%sr1,va) 1245 1248 1246 - mtsp t0, %sr1 /* Restore sr1 */ 1247 - dbit_unlock1 spc,t0 1249 + mtsp t1, %sr1 /* Restore sr1 */ 1248 1250 1251 + tlb_unlock1 spc,t0 1249 1252 rfir 1250 1253 nop 1251 1254 ··· 1264 1269 1265 1270 L2_ptep ptp,pte,t0,va,dtlb_check_alias_20 1266 1271 1267 - dbit_lock spc,t0,t1 1268 - update_ptep spc,ptp,pte,t0,t1 1272 + tlb_lock spc,ptp,pte,t0,t1,dtlb_check_alias_20 1273 + update_accessed ptp,pte,t0,t1 1269 1274 1270 1275 make_insert_tlb spc,pte,prot 1271 1276 1272 - f_extend pte,t0 1277 + f_extend pte,t1 1273 1278 1274 1279 idtlbt pte,prot 1275 - dbit_unlock1 spc,t0 1276 1280 1281 + tlb_unlock1 spc,t0 1277 1282 rfir 1278 1283 nop 1279 1284 ··· 1292 1297 1293 1298 L2_ptep ptp,pte,t0,va,nadtlb_check_alias_20 1294 1299 1295 - dbit_lock spc,t0,t1 1296 - update_ptep spc,ptp,pte,t0,t1 1300 + tlb_lock spc,ptp,pte,t0,t1,nadtlb_check_alias_20 1301 + update_accessed ptp,pte,t0,t1 1297 1302 1298 1303 make_insert_tlb spc,pte,prot 1299 1304 1300 - f_extend pte,t0 1305 + f_extend pte,t1 1301 1306 1302 - idtlbt pte,prot 1303 - dbit_unlock1 spc,t0 1307 + idtlbt pte,prot 1304 1308 1309 + tlb_unlock1 spc,t0 1305 1310 rfir 1306 1311 nop 1307 1312 ··· 1401 1406 1402 1407 L3_ptep ptp,pte,t0,va,itlb_fault 1403 1408 1404 - dbit_lock spc,t0,t1 1405 - update_ptep spc,ptp,pte,t0,t1 1409 + tlb_lock spc,ptp,pte,t0,t1,itlb_fault 1410 + update_accessed ptp,pte,t0,t1 1406 1411 1407 1412 make_insert_tlb spc,pte,prot 1408 1413 1409 1414 iitlbt pte,prot 1410 - dbit_unlock1 spc,t0 1411 1415 1416 + tlb_unlock1 spc,t0 1412 1417 rfir 1413 1418 nop 1414 1419 ··· 1425 1430 1426 1431 L3_ptep ptp,pte,t0,va,naitlb_check_alias_20w 1427 1432 1428 - dbit_lock spc,t0,t1 1429 - update_ptep spc,ptp,pte,t0,t1 1433 + tlb_lock spc,ptp,pte,t0,t1,naitlb_check_alias_20w 1434 + update_accessed ptp,pte,t0,t1 1430 1435 1431 1436 make_insert_tlb spc,pte,prot 1432 1437 1433 1438 iitlbt pte,prot 1434 - dbit_unlock1 spc,t0 1435 1439 1440 + tlb_unlock1 spc,t0 1436 1441 rfir 1437 1442 nop 1438 1443 ··· 1453 1458 1454 1459 L2_ptep ptp,pte,t0,va,itlb_fault 1455 1460 1456 - dbit_lock spc,t0,t1 1457 - update_ptep spc,ptp,pte,t0,t1 1461 + tlb_lock spc,ptp,pte,t0,t1,itlb_fault 1462 + update_accessed ptp,pte,t0,t1 1458 1463 1459 1464 make_insert_tlb_11 spc,pte,prot 1460 1465 1461 - mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ 1466 + mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */ 1462 1467 mtsp spc,%sr1 1463 1468 1464 1469 iitlba pte,(%sr1,va) 1465 1470 iitlbp prot,(%sr1,va) 1466 1471 1467 - mtsp t0, %sr1 /* Restore sr1 */ 1468 - dbit_unlock1 spc,t0 1472 + mtsp t1, %sr1 /* Restore sr1 */ 1469 1473 1474 + tlb_unlock1 spc,t0 1470 1475 rfir 1471 1476 nop 1472 1477 ··· 1477 1482 1478 1483 L2_ptep ptp,pte,t0,va,naitlb_check_alias_11 1479 1484 1480 - dbit_lock spc,t0,t1 1481 - update_ptep spc,ptp,pte,t0,t1 1485 + tlb_lock spc,ptp,pte,t0,t1,naitlb_check_alias_11 1486 + update_accessed ptp,pte,t0,t1 1482 1487 1483 1488 make_insert_tlb_11 spc,pte,prot 1484 1489 1485 - mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ 1490 + mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */ 1486 1491 mtsp spc,%sr1 1487 1492 1488 1493 iitlba pte,(%sr1,va) 1489 1494 iitlbp prot,(%sr1,va) 1490 1495 1491 - mtsp t0, %sr1 /* Restore sr1 */ 1492 - dbit_unlock1 spc,t0 1496 + mtsp t1, %sr1 /* Restore sr1 */ 1493 1497 1498 + tlb_unlock1 spc,t0 1494 1499 rfir 1495 1500 nop 1496 1501 ··· 1511 1516 1512 1517 L2_ptep ptp,pte,t0,va,itlb_fault 1513 1518 1514 - dbit_lock spc,t0,t1 1515 - update_ptep spc,ptp,pte,t0,t1 1519 + tlb_lock spc,ptp,pte,t0,t1,itlb_fault 1520 + update_accessed ptp,pte,t0,t1 1516 1521 1517 1522 make_insert_tlb spc,pte,prot 1518 1523 1519 - f_extend pte,t0 1524 + f_extend pte,t1 1520 1525 1521 1526 iitlbt pte,prot 1522 - dbit_unlock1 spc,t0 1523 1527 1528 + tlb_unlock1 spc,t0 1524 1529 rfir 1525 1530 nop 1526 1531 ··· 1531 1536 1532 1537 L2_ptep ptp,pte,t0,va,naitlb_check_alias_20 1533 1538 1534 - dbit_lock spc,t0,t1 1535 - update_ptep spc,ptp,pte,t0,t1 1539 + tlb_lock spc,ptp,pte,t0,t1,naitlb_check_alias_20 1540 + update_accessed ptp,pte,t0,t1 1536 1541 1537 1542 make_insert_tlb spc,pte,prot 1538 1543 1539 - f_extend pte,t0 1544 + f_extend pte,t1 1540 1545 1541 1546 iitlbt pte,prot 1542 - dbit_unlock1 spc,t0 1543 1547 1548 + tlb_unlock1 spc,t0 1544 1549 rfir 1545 1550 nop 1546 1551 ··· 1563 1568 1564 1569 L3_ptep ptp,pte,t0,va,dbit_fault 1565 1570 1566 - dbit_lock spc,t0,t1 1567 - update_dirty spc,ptp,pte,t1 1571 + tlb_lock spc,ptp,pte,t0,t1,dbit_fault 1572 + update_dirty ptp,pte,t1 1568 1573 1569 1574 make_insert_tlb spc,pte,prot 1570 1575 1571 1576 idtlbt pte,prot 1572 - dbit_unlock0 spc,t0 1573 1577 1578 + tlb_unlock0 spc,t0 1574 1579 rfir 1575 1580 nop 1576 1581 #else ··· 1583 1588 1584 1589 L2_ptep ptp,pte,t0,va,dbit_fault 1585 1590 1586 - dbit_lock spc,t0,t1 1587 - update_dirty spc,ptp,pte,t1 1591 + tlb_lock spc,ptp,pte,t0,t1,dbit_fault 1592 + update_dirty ptp,pte,t1 1588 1593 1589 1594 make_insert_tlb_11 spc,pte,prot 1590 1595 ··· 1595 1600 idtlbp prot,(%sr1,va) 1596 1601 1597 1602 mtsp t1, %sr1 /* Restore sr1 */ 1598 - dbit_unlock0 spc,t0 1599 1603 1604 + tlb_unlock0 spc,t0 1600 1605 rfir 1601 1606 nop 1602 1607 ··· 1607 1612 1608 1613 L2_ptep ptp,pte,t0,va,dbit_fault 1609 1614 1610 - dbit_lock spc,t0,t1 1611 - update_dirty spc,ptp,pte,t1 1615 + tlb_lock spc,ptp,pte,t0,t1,dbit_fault 1616 + update_dirty ptp,pte,t1 1612 1617 1613 1618 make_insert_tlb spc,pte,prot 1614 1619 1615 1620 f_extend pte,t1 1616 1621 1617 - idtlbt pte,prot 1618 - dbit_unlock0 spc,t0 1622 + idtlbt pte,prot 1619 1623 1624 + tlb_unlock0 spc,t0 1620 1625 rfir 1621 1626 nop 1622 1627 #endif
-4
arch/parisc/kernel/traps.c
··· 43 43 44 44 #include "../math-emu/math-emu.h" /* for handle_fpe() */ 45 45 46 - #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) 47 - DEFINE_SPINLOCK(pa_dbit_lock); 48 - #endif 49 - 50 46 static void parisc_show_stack(struct task_struct *task, unsigned long *sp, 51 47 struct pt_regs *regs); 52 48