diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2008-12-18 14:13:38 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2008-12-20 22:21:16 -0500 |
commit | f048aace29e007f2b642097e2da8231e0e9cce2d (patch) | |
tree | 5e99b1d1d37817703132e97388994386a7bee8da /arch/powerpc/include/asm/tlbflush.h | |
parent | 7c03d653cd257793dc40520c94e229b5fd0578e7 (diff) |
powerpc/mm: Add SMP support to no-hash TLB handling
This commit moves the whole no-hash TLB handling out of line into a
new tlb_nohash.c file, and implements some basic SMP support using
IPIs and/or broadcast tlbivax instructions.
Note that I'm using local invalidations for D->I cache coherency.
At worst, if another processor is trying to execute the same and
has the old entry in its TLB, it will just take a fault and re-do
the TLB flush locally (it won't re-do the cache flush in any case).
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/include/asm/tlbflush.h')
-rw-r--r-- | arch/powerpc/include/asm/tlbflush.h | 84 |
1 files changed, 38 insertions, 46 deletions
diff --git a/arch/powerpc/include/asm/tlbflush.h b/arch/powerpc/include/asm/tlbflush.h index 9ed363d3de44..8c39b27c1ed7 100644 --- a/arch/powerpc/include/asm/tlbflush.h +++ b/arch/powerpc/include/asm/tlbflush.h | |||
@@ -6,7 +6,9 @@ | |||
6 | * | 6 | * |
7 | * - flush_tlb_mm(mm) flushes the specified mm context TLB's | 7 | * - flush_tlb_mm(mm) flushes the specified mm context TLB's |
8 | * - flush_tlb_page(vma, vmaddr) flushes one page | 8 | * - flush_tlb_page(vma, vmaddr) flushes one page |
9 | * - local_flush_tlb_page(vmaddr) flushes one page on the local processor | 9 | * - local_flush_tlb_mm(mm) flushes the specified mm context on |
10 | * the local processor | ||
11 | * - local_flush_tlb_page(vma, vmaddr) flushes one page on the local processor | ||
10 | * - flush_tlb_page_nohash(vma, vmaddr) flushes one page if SW loaded TLB | 12 | * - flush_tlb_page_nohash(vma, vmaddr) flushes one page if SW loaded TLB |
11 | * - flush_tlb_range(vma, start, end) flushes a range of pages | 13 | * - flush_tlb_range(vma, start, end) flushes a range of pages |
12 | * - flush_tlb_kernel_range(start, end) flushes a range of kernel pages | 14 | * - flush_tlb_kernel_range(start, end) flushes a range of kernel pages |
@@ -18,7 +20,7 @@ | |||
18 | */ | 20 | */ |
19 | #ifdef __KERNEL__ | 21 | #ifdef __KERNEL__ |
20 | 22 | ||
21 | #if defined(CONFIG_4xx) || defined(CONFIG_8xx) || defined(CONFIG_FSL_BOOKE) | 23 | #ifdef CONFIG_PPC_MMU_NOHASH |
22 | /* | 24 | /* |
23 | * TLB flushing for software loaded TLB chips | 25 | * TLB flushing for software loaded TLB chips |
24 | * | 26 | * |
@@ -31,10 +33,10 @@ | |||
31 | 33 | ||
32 | #define MMU_NO_CONTEXT ((unsigned int)-1) | 34 | #define MMU_NO_CONTEXT ((unsigned int)-1) |
33 | 35 | ||
34 | extern void _tlbie(unsigned long address, unsigned int pid); | ||
35 | extern void _tlbil_all(void); | 36 | extern void _tlbil_all(void); |
36 | extern void _tlbil_pid(unsigned int pid); | 37 | extern void _tlbil_pid(unsigned int pid); |
37 | extern void _tlbil_va(unsigned long address, unsigned int pid); | 38 | extern void _tlbil_va(unsigned long address, unsigned int pid); |
39 | extern void _tlbivax_bcast(unsigned long address, unsigned int pid); | ||
38 | 40 | ||
39 | #if defined(CONFIG_40x) || defined(CONFIG_8xx) | 41 | #if defined(CONFIG_40x) || defined(CONFIG_8xx) |
40 | #define _tlbia() asm volatile ("tlbia; sync" : : : "memory") | 42 | #define _tlbia() asm volatile ("tlbia; sync" : : : "memory") |
@@ -42,48 +44,26 @@ extern void _tlbil_va(unsigned long address, unsigned int pid); | |||
42 | extern void _tlbia(void); | 44 | extern void _tlbia(void); |
43 | #endif | 45 | #endif |
44 | 46 | ||
45 | static inline void local_flush_tlb_mm(struct mm_struct *mm) | 47 | extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, |
46 | { | 48 | unsigned long end); |
47 | _tlbil_pid(mm->context.id); | 49 | extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); |
48 | } | ||
49 | |||
50 | static inline void flush_tlb_mm(struct mm_struct *mm) | ||
51 | { | ||
52 | _tlbil_pid(mm->context.id); | ||
53 | } | ||
54 | |||
55 | static inline void local_flush_tlb_page(unsigned long vmaddr) | ||
56 | { | ||
57 | _tlbil_va(vmaddr, 0); | ||
58 | } | ||
59 | |||
60 | static inline void flush_tlb_page(struct vm_area_struct *vma, | ||
61 | unsigned long vmaddr) | ||
62 | { | ||
63 | _tlbil_va(vmaddr, vma ? vma->vm_mm->context.id : 0); | ||
64 | } | ||
65 | 50 | ||
66 | static inline void flush_tlb_page_nohash(struct vm_area_struct *vma, | 51 | extern void local_flush_tlb_mm(struct mm_struct *mm); |
67 | unsigned long vmaddr) | 52 | extern void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); |
68 | { | ||
69 | flush_tlb_page(vma, vmaddr); | ||
70 | } | ||
71 | 53 | ||
72 | static inline void flush_tlb_range(struct vm_area_struct *vma, | 54 | #ifdef CONFIG_SMP |
73 | unsigned long start, unsigned long end) | 55 | extern void flush_tlb_mm(struct mm_struct *mm); |
74 | { | 56 | extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); |
75 | _tlbil_pid(vma->vm_mm->context.id); | 57 | #else |
76 | } | 58 | #define flush_tlb_mm(mm) local_flush_tlb_mm(mm) |
59 | #define flush_tlb_page(vma,addr) local_flush_tlb_page(vma,addr) | ||
60 | #endif | ||
61 | #define flush_tlb_page_nohash(vma,addr) flush_tlb_page(vma,addr) | ||
77 | 62 | ||
78 | static inline void flush_tlb_kernel_range(unsigned long start, | 63 | #elif defined(CONFIG_PPC_STD_MMU_32) |
79 | unsigned long end) | ||
80 | { | ||
81 | _tlbil_pid(0); | ||
82 | } | ||
83 | 64 | ||
84 | #elif defined(CONFIG_PPC32) | ||
85 | /* | 65 | /* |
86 | * TLB flushing for "classic" hash-MMMU 32-bit CPUs, 6xx, 7xx, 7xxx | 66 | * TLB flushing for "classic" hash-MMU 32-bit CPUs, 6xx, 7xx, 7xxx |
87 | */ | 67 | */ |
88 | extern void _tlbie(unsigned long address); | 68 | extern void _tlbie(unsigned long address); |
89 | extern void _tlbia(void); | 69 | extern void _tlbia(void); |
@@ -94,14 +74,20 @@ extern void flush_tlb_page_nohash(struct vm_area_struct *vma, unsigned long addr | |||
94 | extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | 74 | extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, |
95 | unsigned long end); | 75 | unsigned long end); |
96 | extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); | 76 | extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); |
97 | static inline void local_flush_tlb_page(unsigned long vmaddr) | 77 | static inline void local_flush_tlb_page(struct vm_area_struct *vma, |
78 | unsigned long vmaddr) | ||
98 | { | 79 | { |
99 | flush_tlb_page(NULL, vmaddr); | 80 | flush_tlb_page(vma, vmaddr); |
81 | } | ||
82 | static inline void local_flush_tlb_mm(struct mm_struct *mm) | ||
83 | { | ||
84 | flush_tlb_mm(mm); | ||
100 | } | 85 | } |
101 | 86 | ||
102 | #else | 87 | #elif defined(CONFIG_PPC_STD_MMU_64) |
88 | |||
103 | /* | 89 | /* |
104 | * TLB flushing for 64-bit has-MMU CPUs | 90 | * TLB flushing for 64-bit hash-MMU CPUs |
105 | */ | 91 | */ |
106 | 92 | ||
107 | #include <linux/percpu.h> | 93 | #include <linux/percpu.h> |
@@ -151,11 +137,16 @@ extern void flush_hash_page(unsigned long va, real_pte_t pte, int psize, | |||
151 | extern void flush_hash_range(unsigned long number, int local); | 137 | extern void flush_hash_range(unsigned long number, int local); |
152 | 138 | ||
153 | 139 | ||
140 | static inline void local_flush_tlb_mm(struct mm_struct *mm) | ||
141 | { | ||
142 | } | ||
143 | |||
154 | static inline void flush_tlb_mm(struct mm_struct *mm) | 144 | static inline void flush_tlb_mm(struct mm_struct *mm) |
155 | { | 145 | { |
156 | } | 146 | } |
157 | 147 | ||
158 | static inline void local_flush_tlb_page(unsigned long vmaddr) | 148 | static inline void local_flush_tlb_page(struct vm_area_struct *vma, |
149 | unsigned long vmaddr) | ||
159 | { | 150 | { |
160 | } | 151 | } |
161 | 152 | ||
@@ -183,7 +174,8 @@ static inline void flush_tlb_kernel_range(unsigned long start, | |||
183 | extern void __flush_hash_table_range(struct mm_struct *mm, unsigned long start, | 174 | extern void __flush_hash_table_range(struct mm_struct *mm, unsigned long start, |
184 | unsigned long end); | 175 | unsigned long end); |
185 | 176 | ||
186 | 177 | #else | |
178 | #error Unsupported MMU type | ||
187 | #endif | 179 | #endif |
188 | 180 | ||
189 | #endif /*__KERNEL__ */ | 181 | #endif /*__KERNEL__ */ |