diff options
author | Kumar Gala <galak@kernel.crashing.org> | 2008-07-15 17:12:25 -0400 |
---|---|---|
committer | Kumar Gala <galak@kernel.crashing.org> | 2008-09-24 17:29:40 -0400 |
commit | 0ba3418b8b1c85ee1771c63f1dd12041614e56ff (patch) | |
tree | 6f77bf668e76725710aae5126054eebd5913d319 /arch/powerpc | |
parent | 1afb7f809bfb8fad9eec9419f3dfd75cee746ebd (diff) |
powerpc: Introduce local (non-broadcast) forms of tlb invalidates
Introduced a new set of low level tlb invalidate functions that do not
broadcast invalidates on the bus:
_tlbil_all - invalidate all
_tlbil_pid - invalidate based on process id (or mm context)
_tlbil_va - invalidate based on virtual address (ea + pid)
On non-SMP configs _tlbil_all should be functionally equivalent to _tlbia and
_tlbil_va should be functionally equivalent to _tlbie.
The intent of this change is to handle SMP based invalidates via IPIs instead
of broadcasts as the mechanism scales better for larger number of cores.
On e500 (fsl-booke mmu) based cores move to using MMUCSR for invalidate alls
and tlbsx/tlbwe for invalidate virtual address.
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/include/asm/reg_booke.h | 7 | ||||
-rw-r--r-- | arch/powerpc/include/asm/tlbflush.h | 13 | ||||
-rw-r--r-- | arch/powerpc/kernel/misc_32.S | 54 | ||||
-rw-r--r-- | arch/powerpc/kernel/ppc_ksyms.c | 3 |
4 files changed, 72 insertions, 5 deletions
diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h index be980f4ee495..67453766bff1 100644 --- a/arch/powerpc/include/asm/reg_booke.h +++ b/arch/powerpc/include/asm/reg_booke.h | |||
@@ -109,6 +109,7 @@ | |||
109 | #define SPRN_EVPR 0x3D6 /* Exception Vector Prefix Register */ | 109 | #define SPRN_EVPR 0x3D6 /* Exception Vector Prefix Register */ |
110 | #define SPRN_L1CSR0 0x3F2 /* L1 Cache Control and Status Register 0 */ | 110 | #define SPRN_L1CSR0 0x3F2 /* L1 Cache Control and Status Register 0 */ |
111 | #define SPRN_L1CSR1 0x3F3 /* L1 Cache Control and Status Register 1 */ | 111 | #define SPRN_L1CSR1 0x3F3 /* L1 Cache Control and Status Register 1 */ |
112 | #define SPRN_MMUCSR0 0x3F4 /* MMU Control and Status Register 0 */ | ||
112 | #define SPRN_PIT 0x3DB /* Programmable Interval Timer */ | 113 | #define SPRN_PIT 0x3DB /* Programmable Interval Timer */ |
113 | #define SPRN_BUCSR 0x3F5 /* Branch Unit Control and Status */ | 114 | #define SPRN_BUCSR 0x3F5 /* Branch Unit Control and Status */ |
114 | #define SPRN_L2CSR0 0x3F9 /* L2 Data Cache Control and Status Register 0 */ | 115 | #define SPRN_L2CSR0 0x3F9 /* L2 Data Cache Control and Status Register 0 */ |
@@ -410,6 +411,12 @@ | |||
410 | #define L2CSR0_L2LOA 0x00000080 /* L2 Cache Lock Overflow Allocate */ | 411 | #define L2CSR0_L2LOA 0x00000080 /* L2 Cache Lock Overflow Allocate */ |
411 | #define L2CSR0_L2LO 0x00000020 /* L2 Cache Lock Overflow */ | 412 | #define L2CSR0_L2LO 0x00000020 /* L2 Cache Lock Overflow */ |
412 | 413 | ||
414 | /* Bit definitions for MMUCSR0 */ | ||
415 | #define MMUCSR0_TLB1FI 0x00000002 /* TLB1 Flash invalidate */ | ||
416 | #define MMUCSR0_TLB0FI 0x00000004 /* TLB0 Flash invalidate */ | ||
417 | #define MMUCSR0_TLB2FI 0x00000040 /* TLB2 Flash invalidate */ | ||
418 | #define MMUCSR0_TLB3FI 0x00000020 /* TLB3 Flash invalidate */ | ||
419 | |||
413 | /* Bit definitions for SGR. */ | 420 | /* Bit definitions for SGR. */ |
414 | #define SGR_NORMAL 0 /* Speculative fetching allowed. */ | 421 | #define SGR_NORMAL 0 /* Speculative fetching allowed. */ |
415 | #define SGR_GUARDED 1 /* Speculative fetching disallowed. */ | 422 | #define SGR_GUARDED 1 /* Speculative fetching disallowed. */ |
diff --git a/arch/powerpc/include/asm/tlbflush.h b/arch/powerpc/include/asm/tlbflush.h index 361cd5c7a32b..a2c6bfd85fb7 100644 --- a/arch/powerpc/include/asm/tlbflush.h +++ b/arch/powerpc/include/asm/tlbflush.h | |||
@@ -29,6 +29,9 @@ | |||
29 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
30 | 30 | ||
31 | extern void _tlbie(unsigned long address, unsigned int pid); | 31 | extern void _tlbie(unsigned long address, unsigned int pid); |
32 | extern void _tlbil_all(void); | ||
33 | extern void _tlbil_pid(unsigned int pid); | ||
34 | extern void _tlbil_va(unsigned long address, unsigned int pid); | ||
32 | 35 | ||
33 | #if defined(CONFIG_40x) || defined(CONFIG_8xx) | 36 | #if defined(CONFIG_40x) || defined(CONFIG_8xx) |
34 | #define _tlbia() asm volatile ("tlbia; sync" : : : "memory") | 37 | #define _tlbia() asm volatile ("tlbia; sync" : : : "memory") |
@@ -38,31 +41,31 @@ extern void _tlbia(void); | |||
38 | 41 | ||
39 | static inline void flush_tlb_mm(struct mm_struct *mm) | 42 | static inline void flush_tlb_mm(struct mm_struct *mm) |
40 | { | 43 | { |
41 | _tlbia(); | 44 | _tlbil_pid(mm->context.id); |
42 | } | 45 | } |
43 | 46 | ||
44 | static inline void flush_tlb_page(struct vm_area_struct *vma, | 47 | static inline void flush_tlb_page(struct vm_area_struct *vma, |
45 | unsigned long vmaddr) | 48 | unsigned long vmaddr) |
46 | { | 49 | { |
47 | _tlbie(vmaddr, vma ? vma->vm_mm->context.id : 0); | 50 | _tlbil_va(vmaddr, vma ? vma->vm_mm->context.id : 0); |
48 | } | 51 | } |
49 | 52 | ||
50 | static inline void flush_tlb_page_nohash(struct vm_area_struct *vma, | 53 | static inline void flush_tlb_page_nohash(struct vm_area_struct *vma, |
51 | unsigned long vmaddr) | 54 | unsigned long vmaddr) |
52 | { | 55 | { |
53 | _tlbie(vmaddr, vma ? vma->vm_mm->context.id : 0); | 56 | flush_tlb_page(vma, vmaddr); |
54 | } | 57 | } |
55 | 58 | ||
56 | static inline void flush_tlb_range(struct vm_area_struct *vma, | 59 | static inline void flush_tlb_range(struct vm_area_struct *vma, |
57 | unsigned long start, unsigned long end) | 60 | unsigned long start, unsigned long end) |
58 | { | 61 | { |
59 | _tlbia(); | 62 | _tlbil_pid(vma->vm_mm->context.id); |
60 | } | 63 | } |
61 | 64 | ||
62 | static inline void flush_tlb_kernel_range(unsigned long start, | 65 | static inline void flush_tlb_kernel_range(unsigned long start, |
63 | unsigned long end) | 66 | unsigned long end) |
64 | { | 67 | { |
65 | _tlbia(); | 68 | _tlbil_pid(0); |
66 | } | 69 | } |
67 | 70 | ||
68 | #elif defined(CONFIG_PPC32) | 71 | #elif defined(CONFIG_PPC32) |
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 7a6dfbca7682..e9c8ab6eabfe 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S | |||
@@ -274,6 +274,10 @@ _GLOBAL(real_writeb) | |||
274 | /* | 274 | /* |
275 | * Flush MMU TLB | 275 | * Flush MMU TLB |
276 | */ | 276 | */ |
277 | #ifndef CONFIG_FSL_BOOKE | ||
278 | _GLOBAL(_tlbil_all) | ||
279 | _GLOBAL(_tlbil_pid) | ||
280 | #endif | ||
277 | _GLOBAL(_tlbia) | 281 | _GLOBAL(_tlbia) |
278 | #if defined(CONFIG_40x) | 282 | #if defined(CONFIG_40x) |
279 | sync /* Flush to memory before changing mapping */ | 283 | sync /* Flush to memory before changing mapping */ |
@@ -344,6 +348,9 @@ _GLOBAL(_tlbia) | |||
344 | /* | 348 | /* |
345 | * Flush MMU TLB for a particular address | 349 | * Flush MMU TLB for a particular address |
346 | */ | 350 | */ |
351 | #ifndef CONFIG_FSL_BOOKE | ||
352 | _GLOBAL(_tlbil_va) | ||
353 | #endif | ||
347 | _GLOBAL(_tlbie) | 354 | _GLOBAL(_tlbie) |
348 | #if defined(CONFIG_40x) | 355 | #if defined(CONFIG_40x) |
349 | /* We run the search with interrupts disabled because we have to change | 356 | /* We run the search with interrupts disabled because we have to change |
@@ -436,6 +443,53 @@ _GLOBAL(_tlbie) | |||
436 | #endif /* ! CONFIG_40x */ | 443 | #endif /* ! CONFIG_40x */ |
437 | blr | 444 | blr |
438 | 445 | ||
446 | #if defined(CONFIG_FSL_BOOKE) | ||
447 | /* | ||
448 | * Flush MMU TLB, but only on the local processor (no broadcast) | ||
449 | */ | ||
450 | _GLOBAL(_tlbil_all) | ||
451 | #define MMUCSR0_TLBFI (MMUCSR0_TLB0FI | MMUCSR0_TLB1FI | \ | ||
452 | MMUCSR0_TLB2FI | MMUCSR0_TLB3FI) | ||
453 | li r3,(MMUCSR0_TLBFI)@l | ||
454 | mtspr SPRN_MMUCSR0, r3 | ||
455 | 1: | ||
456 | mfspr r3,SPRN_MMUCSR0 | ||
457 | andi. r3,r3,MMUCSR0_TLBFI@l | ||
458 | bne 1b | ||
459 | blr | ||
460 | |||
461 | /* | ||
462 | * Flush MMU TLB for a particular process id, but only on the local processor | ||
463 | * (no broadcast) | ||
464 | */ | ||
465 | _GLOBAL(_tlbil_pid) | ||
466 | /* we currently do an invalidate all since we don't have per pid invalidate */ | ||
467 | li r3,(MMUCSR0_TLBFI)@l | ||
468 | mtspr SPRN_MMUCSR0, r3 | ||
469 | 1: | ||
470 | mfspr r3,SPRN_MMUCSR0 | ||
471 | andi. r3,r3,MMUCSR0_TLBFI@l | ||
472 | bne 1b | ||
473 | blr | ||
474 | |||
475 | /* | ||
476 | * Flush MMU TLB for a particular address, but only on the local processor | ||
477 | * (no broadcast) | ||
478 | */ | ||
479 | _GLOBAL(_tlbil_va) | ||
480 | slwi r4,r4,16 | ||
481 | mtspr SPRN_MAS6,r4 /* assume AS=0 for now */ | ||
482 | tlbsx 0,r3 | ||
483 | mfspr r4,SPRN_MAS1 /* check valid */ | ||
484 | andis. r3,r4,MAS1_VALID@h | ||
485 | beqlr | ||
486 | rlwinm r4,r4,0,1,31 | ||
487 | mtspr SPRN_MAS1,r4 | ||
488 | tlbwe | ||
489 | blr | ||
490 | #endif /* CONFIG_FSL_BOOKE */ | ||
491 | |||
492 | |||
439 | /* | 493 | /* |
440 | * Flush instruction cache. | 494 | * Flush instruction cache. |
441 | * This is a no-op on the 601. | 495 | * This is a no-op on the 601. |
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index e1ea4fe5cfbd..8edc2359c419 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c | |||
@@ -119,6 +119,9 @@ EXPORT_SYMBOL(flush_instruction_cache); | |||
119 | EXPORT_SYMBOL(flush_tlb_kernel_range); | 119 | EXPORT_SYMBOL(flush_tlb_kernel_range); |
120 | EXPORT_SYMBOL(flush_tlb_page); | 120 | EXPORT_SYMBOL(flush_tlb_page); |
121 | EXPORT_SYMBOL(_tlbie); | 121 | EXPORT_SYMBOL(_tlbie); |
122 | #if defined(CONFIG_4xx) || defined(CONFIG_8xx) || defined(CONFIG_FSL_BOOKE) | ||
123 | EXPORT_SYMBOL(_tlbil_va); | ||
124 | #endif | ||
122 | #endif | 125 | #endif |
123 | EXPORT_SYMBOL(__flush_icache_range); | 126 | EXPORT_SYMBOL(__flush_icache_range); |
124 | EXPORT_SYMBOL(flush_dcache_range); | 127 | EXPORT_SYMBOL(flush_dcache_range); |