1
2
3
4
5
6
7
8
9
10
11
12
13#ifndef _ASM_GENERIC__TLB_H
14#define _ASM_GENERIC__TLB_H
15
16#include <linux/swap.h>
17#include <linux/quicklist.h>
18#include <asm/pgalloc.h>
19#include <asm/tlbflush.h>
20
21
22
23
24
25#ifdef CONFIG_SMP
26 #ifdef ARCH_FREE_PTR_NR
27 #define FREE_PTR_NR ARCH_FREE_PTR_NR
28 #else
29 #define FREE_PTE_NR 506
30 #endif
31 #define tlb_fast_mode(tlb) ((tlb)->nr == ~0U)
32#else
33 #define FREE_PTE_NR 1
34 #define tlb_fast_mode(tlb) 1
35#endif
36
37
38
39
40struct mmu_gather {
41 struct mm_struct *mm;
42 unsigned int nr;
43 unsigned int need_flush;
44 unsigned int fullmm;
45 struct page * pages[FREE_PTE_NR];
46};
47
48
49DECLARE_PER_CPU(struct mmu_gather, mmu_gathers);
50
51
52
53
54static inline struct mmu_gather *
55tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush)
56{
57 struct mmu_gather *tlb = &get_cpu_var(mmu_gathers);
58
59 tlb->mm = mm;
60
61
62 tlb->nr = num_online_cpus() > 1 ? 0U : ~0U;
63
64 tlb->fullmm = full_mm_flush;
65
66 return tlb;
67}
68
69static inline void
70tlb_flush_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
71{
72 if (!tlb->need_flush)
73 return;
74 tlb->need_flush = 0;
75 tlb_flush(tlb);
76 if (!tlb_fast_mode(tlb)) {
77 free_pages_and_swap_cache(tlb->pages, tlb->nr);
78 tlb->nr = 0;
79 }
80}
81
82
83
84
85
86static inline void
87tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
88{
89 tlb_flush_mmu(tlb, start, end);
90
91
92 check_pgt_cache();
93
94 put_cpu_var(mmu_gathers);
95}
96
97
98
99
100
101
102static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
103{
104 tlb->need_flush = 1;
105 if (tlb_fast_mode(tlb)) {
106 free_page_and_swap_cache(page);
107 return;
108 }
109 tlb->pages[tlb->nr++] = page;
110 if (tlb->nr >= FREE_PTE_NR)
111 tlb_flush_mmu(tlb, 0, 0);
112}
113
114
115
116
117
118
119
120
121#define tlb_remove_tlb_entry(tlb, ptep, address) \
122 do { \
123 tlb->need_flush = 1; \
124 __tlb_remove_tlb_entry(tlb, ptep, address); \
125 } while (0)
126
127#define pte_free_tlb(tlb, ptep) \
128 do { \
129 tlb->need_flush = 1; \
130 __pte_free_tlb(tlb, ptep); \
131 } while (0)
132
133#ifndef __ARCH_HAS_4LEVEL_HACK
134#define pud_free_tlb(tlb, pudp) \
135 do { \
136 tlb->need_flush = 1; \
137 __pud_free_tlb(tlb, pudp); \
138 } while (0)
139#endif
140
141#define pmd_free_tlb(tlb, pmdp) \
142 do { \
143 tlb->need_flush = 1; \
144 __pmd_free_tlb(tlb, pmdp); \
145 } while (0)
146
147#define tlb_migrate_finish(mm) do {} while (0)
148
149#endif
150