aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/include/asm/tlb.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/include/asm/tlb.h')
-rw-r--r--arch/arm/include/asm/tlb.h38
1 files changed, 36 insertions, 2 deletions
diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h
index f1a0dace3efe..3cadb726ec88 100644
--- a/arch/arm/include/asm/tlb.h
+++ b/arch/arm/include/asm/tlb.h
@@ -35,12 +35,39 @@
35 35
36#define MMU_GATHER_BUNDLE 8 36#define MMU_GATHER_BUNDLE 8
37 37
38#ifdef CONFIG_HAVE_RCU_TABLE_FREE
39static inline void __tlb_remove_table(void *_table)
40{
41 free_page_and_swap_cache((struct page *)_table);
42}
43
44struct mmu_table_batch {
45 struct rcu_head rcu;
46 unsigned int nr;
47 void *tables[0];
48};
49
50#define MAX_TABLE_BATCH \
51 ((PAGE_SIZE - sizeof(struct mmu_table_batch)) / sizeof(void *))
52
53extern void tlb_table_flush(struct mmu_gather *tlb);
54extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
55
56#define tlb_remove_entry(tlb, entry) tlb_remove_table(tlb, entry)
57#else
58#define tlb_remove_entry(tlb, entry) tlb_remove_page(tlb, entry)
59#endif /* CONFIG_HAVE_RCU_TABLE_FREE */
60
38/* 61/*
39 * TLB handling. This allows us to remove pages from the page 62 * TLB handling. This allows us to remove pages from the page
40 * tables, and efficiently handle the TLB issues. 63 * tables, and efficiently handle the TLB issues.
41 */ 64 */
42struct mmu_gather { 65struct mmu_gather {
43 struct mm_struct *mm; 66 struct mm_struct *mm;
67#ifdef CONFIG_HAVE_RCU_TABLE_FREE
68 struct mmu_table_batch *batch;
69 unsigned int need_flush;
70#endif
44 unsigned int fullmm; 71 unsigned int fullmm;
45 struct vm_area_struct *vma; 72 struct vm_area_struct *vma;
46 unsigned long start, end; 73 unsigned long start, end;
@@ -101,6 +128,9 @@ static inline void __tlb_alloc_page(struct mmu_gather *tlb)
101static inline void tlb_flush_mmu_tlbonly(struct mmu_gather *tlb) 128static inline void tlb_flush_mmu_tlbonly(struct mmu_gather *tlb)
102{ 129{
103 tlb_flush(tlb); 130 tlb_flush(tlb);
131#ifdef CONFIG_HAVE_RCU_TABLE_FREE
132 tlb_table_flush(tlb);
133#endif
104} 134}
105 135
106static inline void tlb_flush_mmu_free(struct mmu_gather *tlb) 136static inline void tlb_flush_mmu_free(struct mmu_gather *tlb)
@@ -129,6 +159,10 @@ tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start
129 tlb->pages = tlb->local; 159 tlb->pages = tlb->local;
130 tlb->nr = 0; 160 tlb->nr = 0;
131 __tlb_alloc_page(tlb); 161 __tlb_alloc_page(tlb);
162
163#ifdef CONFIG_HAVE_RCU_TABLE_FREE
164 tlb->batch = NULL;
165#endif
132} 166}
133 167
134static inline void 168static inline void
@@ -205,7 +239,7 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
205 tlb_add_flush(tlb, addr + SZ_1M); 239 tlb_add_flush(tlb, addr + SZ_1M);
206#endif 240#endif
207 241
208 tlb_remove_page(tlb, pte); 242 tlb_remove_entry(tlb, pte);
209} 243}
210 244
211static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp, 245static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp,
@@ -213,7 +247,7 @@ static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp,
213{ 247{
214#ifdef CONFIG_ARM_LPAE 248#ifdef CONFIG_ARM_LPAE
215 tlb_add_flush(tlb, addr); 249 tlb_add_flush(tlb, addr);
216 tlb_remove_page(tlb, virt_to_page(pmdp)); 250 tlb_remove_entry(tlb, virt_to_page(pmdp));
217#endif 251#endif
218} 252}
219 253