aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/include/asm/tlbflush.h
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2008-12-18 14:13:38 -0500
committerPaul Mackerras <paulus@samba.org>2008-12-20 22:21:16 -0500
commitf048aace29e007f2b642097e2da8231e0e9cce2d (patch)
tree5e99b1d1d37817703132e97388994386a7bee8da /arch/powerpc/include/asm/tlbflush.h
parent7c03d653cd257793dc40520c94e229b5fd0578e7 (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.h84
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
34extern void _tlbie(unsigned long address, unsigned int pid);
35extern void _tlbil_all(void); 36extern void _tlbil_all(void);
36extern void _tlbil_pid(unsigned int pid); 37extern void _tlbil_pid(unsigned int pid);
37extern void _tlbil_va(unsigned long address, unsigned int pid); 38extern void _tlbil_va(unsigned long address, unsigned int pid);
39extern 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);
42extern void _tlbia(void); 44extern void _tlbia(void);
43#endif 45#endif
44 46
45static inline void local_flush_tlb_mm(struct mm_struct *mm) 47extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
46{ 48 unsigned long end);
47 _tlbil_pid(mm->context.id); 49extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
48}
49
50static inline void flush_tlb_mm(struct mm_struct *mm)
51{
52 _tlbil_pid(mm->context.id);
53}
54
55static inline void local_flush_tlb_page(unsigned long vmaddr)
56{
57 _tlbil_va(vmaddr, 0);
58}
59
60static 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
66static inline void flush_tlb_page_nohash(struct vm_area_struct *vma, 51extern void local_flush_tlb_mm(struct mm_struct *mm);
67 unsigned long vmaddr) 52extern void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
68{
69 flush_tlb_page(vma, vmaddr);
70}
71 53
72static inline void flush_tlb_range(struct vm_area_struct *vma, 54#ifdef CONFIG_SMP
73 unsigned long start, unsigned long end) 55extern void flush_tlb_mm(struct mm_struct *mm);
74{ 56extern 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
78static 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 */
88extern void _tlbie(unsigned long address); 68extern void _tlbie(unsigned long address);
89extern void _tlbia(void); 69extern void _tlbia(void);
@@ -94,14 +74,20 @@ extern void flush_tlb_page_nohash(struct vm_area_struct *vma, unsigned long addr
94extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, 74extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
95 unsigned long end); 75 unsigned long end);
96extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); 76extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
97static inline void local_flush_tlb_page(unsigned long vmaddr) 77static 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}
82static 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,
151extern void flush_hash_range(unsigned long number, int local); 137extern void flush_hash_range(unsigned long number, int local);
152 138
153 139
140static inline void local_flush_tlb_mm(struct mm_struct *mm)
141{
142}
143
154static inline void flush_tlb_mm(struct mm_struct *mm) 144static inline void flush_tlb_mm(struct mm_struct *mm)
155{ 145{
156} 146}
157 147
158static inline void local_flush_tlb_page(unsigned long vmaddr) 148static 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,
183extern void __flush_hash_table_range(struct mm_struct *mm, unsigned long start, 174extern 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__ */