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

Merge branch 'parisc-4.2-1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux

Pull parisc fixes from Helge Deller:
"We have one important patch from Dave Anglin and myself which fixes
PTE/TLB race conditions which caused random segmentation faults on our
debian buildd servers, and one patch from Alex Ivanov which speeds up
the graphical text console on the STI framebuffer driver"

* 'parisc-4.2-1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux:
parisc: Fix some PTE/TLB race conditions and optimize __flush_tlb_range based on timing results
stifb: Implement hardware accelerated copyarea

+250 -170
+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
+38 -2
drivers/video/fbdev/stifb.c
··· 121 121 #define REG_3 0x0004a0 122 122 #define REG_4 0x000600 123 123 #define REG_6 0x000800 124 + #define REG_7 0x000804 124 125 #define REG_8 0x000820 125 126 #define REG_9 0x000a04 126 127 #define REG_10 0x018000 ··· 136 135 #define REG_21 0x200218 137 136 #define REG_22 0x0005a0 138 137 #define REG_23 0x0005c0 138 + #define REG_24 0x000808 139 + #define REG_25 0x000b00 139 140 #define REG_26 0x200118 140 141 #define REG_27 0x200308 141 142 #define REG_32 0x21003c ··· 431 428 432 429 #define SET_LENXY_START_RECFILL(fb, lenxy) \ 433 430 WRITE_WORD(lenxy, fb, REG_9) 431 + 432 + #define SETUP_COPYAREA(fb) \ 433 + WRITE_BYTE(0, fb, REG_16b1) 434 434 435 435 static void 436 436 HYPER_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable) ··· 1010 1004 return 0; 1011 1005 } 1012 1006 1007 + static void 1008 + stifb_copyarea(struct fb_info *info, const struct fb_copyarea *area) 1009 + { 1010 + struct stifb_info *fb = container_of(info, struct stifb_info, info); 1011 + 1012 + SETUP_COPYAREA(fb); 1013 + 1014 + SETUP_HW(fb); 1015 + if (fb->info.var.bits_per_pixel == 32) { 1016 + WRITE_WORD(0xBBA0A000, fb, REG_10); 1017 + 1018 + NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, 0xffffffff); 1019 + } else { 1020 + WRITE_WORD(fb->id == S9000_ID_HCRX ? 0x13a02000 : 0x13a01000, fb, REG_10); 1021 + 1022 + NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, 0xff); 1023 + } 1024 + 1025 + NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb, 1026 + IBOvals(RopSrc, MaskAddrOffset(0), 1027 + BitmapExtent08, StaticReg(1), 1028 + DataDynamic, MaskOtc, BGx(0), FGx(0))); 1029 + 1030 + WRITE_WORD(((area->sx << 16) | area->sy), fb, REG_24); 1031 + WRITE_WORD(((area->width << 16) | area->height), fb, REG_7); 1032 + WRITE_WORD(((area->dx << 16) | area->dy), fb, REG_25); 1033 + 1034 + SETUP_FB(fb); 1035 + } 1036 + 1013 1037 static void __init 1014 1038 stifb_init_display(struct stifb_info *fb) 1015 1039 { ··· 1105 1069 .fb_setcolreg = stifb_setcolreg, 1106 1070 .fb_blank = stifb_blank, 1107 1071 .fb_fillrect = cfb_fillrect, 1108 - .fb_copyarea = cfb_copyarea, 1072 + .fb_copyarea = stifb_copyarea, 1109 1073 .fb_imageblit = cfb_imageblit, 1110 1074 }; 1111 1075 ··· 1294 1258 info->fbops = &stifb_ops; 1295 1259 info->screen_base = ioremap_nocache(REGION_BASE(fb,1), fix->smem_len); 1296 1260 info->screen_size = fix->smem_len; 1297 - info->flags = FBINFO_DEFAULT; 1261 + info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA; 1298 1262 info->pseudo_palette = &fb->pseudo_palette; 1299 1263 1300 1264 /* This has to be done !!! */