1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#ifndef _ASM_GENERIC__TLB_H
16#define _ASM_GENERIC__TLB_H
17
18#include <linux/swap.h>
19#include <asm/pgalloc.h>
20#include <asm/tlbflush.h>
21
22#ifdef CONFIG_HAVE_RCU_TABLE_FREE
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51struct mmu_table_batch {
52 struct rcu_head rcu;
53 unsigned int nr;
54 void *tables[0];
55};
56
57#define MAX_TABLE_BATCH \
58 ((PAGE_SIZE - sizeof(struct mmu_table_batch)) / sizeof(void *))
59
60extern void tlb_table_flush(struct mmu_gather *tlb);
61extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
62
63#endif
64
65
66
67
68
69#define MMU_GATHER_BUNDLE 8
70
71struct mmu_gather_batch {
72 struct mmu_gather_batch *next;
73 unsigned int nr;
74 unsigned int max;
75 struct page *pages[0];
76};
77
78#define MAX_GATHER_BATCH \
79 ((PAGE_SIZE - sizeof(struct mmu_gather_batch)) / sizeof(void *))
80
81
82
83
84struct mmu_gather {
85 struct mm_struct *mm;
86#ifdef CONFIG_HAVE_RCU_TABLE_FREE
87 struct mmu_table_batch *batch;
88#endif
89 unsigned long start;
90 unsigned long end;
91 unsigned int need_flush : 1,
92 fast_mode : 1;
93
94 unsigned int fullmm;
95
96 struct mmu_gather_batch *active;
97 struct mmu_gather_batch local;
98 struct page *__pages[MMU_GATHER_BUNDLE];
99};
100
101#define HAVE_GENERIC_MMU_GATHER
102
103static inline int tlb_fast_mode(struct mmu_gather *tlb)
104{
105#ifdef CONFIG_SMP
106 return tlb->fast_mode;
107#else
108
109
110
111
112 return 1;
113#endif
114}
115
116void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, bool fullmm);
117void tlb_flush_mmu(struct mmu_gather *tlb);
118void tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start,
119 unsigned long end);
120int __tlb_remove_page(struct mmu_gather *tlb, struct page *page);
121
122
123
124
125
126static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
127{
128 if (!__tlb_remove_page(tlb, page))
129 tlb_flush_mmu(tlb);
130}
131
132
133
134
135
136
137
138
139#define tlb_remove_tlb_entry(tlb, ptep, address) \
140 do { \
141 tlb->need_flush = 1; \
142 __tlb_remove_tlb_entry(tlb, ptep, address); \
143 } while (0)
144
145
146
147
148
149#ifndef __tlb_remove_pmd_tlb_entry
150#define __tlb_remove_pmd_tlb_entry(tlb, pmdp, address) do {} while (0)
151#endif
152
153#define tlb_remove_pmd_tlb_entry(tlb, pmdp, address) \
154 do { \
155 tlb->need_flush = 1; \
156 __tlb_remove_pmd_tlb_entry(tlb, pmdp, address); \
157 } while (0)
158
159#define pte_free_tlb(tlb, ptep, address) \
160 do { \
161 tlb->need_flush = 1; \
162 __pte_free_tlb(tlb, ptep, address); \
163 } while (0)
164
165#ifndef __ARCH_HAS_4LEVEL_HACK
166#define pud_free_tlb(tlb, pudp, address) \
167 do { \
168 tlb->need_flush = 1; \
169 __pud_free_tlb(tlb, pudp, address); \
170 } while (0)
171#endif
172
173#define pmd_free_tlb(tlb, pmdp, address) \
174 do { \
175 tlb->need_flush = 1; \
176 __pmd_free_tlb(tlb, pmdp, address); \
177 } while (0)
178
179#define tlb_migrate_finish(mm) do {} while (0)
180
181#endif
182