@@ -61,20 +61,22 @@ static inline int ioremap_pmd_enabled(void) { return 0; }
61
61
#endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */
62
62
63
63
static int ioremap_pte_range (pmd_t * pmd , unsigned long addr ,
64
- unsigned long end , phys_addr_t phys_addr , pgprot_t prot )
64
+ unsigned long end , phys_addr_t phys_addr , pgprot_t prot ,
65
+ pgtbl_mod_mask * mask )
65
66
{
66
67
pte_t * pte ;
67
68
u64 pfn ;
68
69
69
70
pfn = phys_addr >> PAGE_SHIFT ;
70
- pte = pte_alloc_kernel (pmd , addr );
71
+ pte = pte_alloc_kernel_track (pmd , addr , mask );
71
72
if (!pte )
72
73
return - ENOMEM ;
73
74
do {
74
75
BUG_ON (!pte_none (* pte ));
75
76
set_pte_at (& init_mm , addr , pte , pfn_pte (pfn , prot ));
76
77
pfn ++ ;
77
78
} while (pte ++ , addr += PAGE_SIZE , addr != end );
79
+ * mask |= PGTBL_PTE_MODIFIED ;
78
80
return 0 ;
79
81
}
80
82
@@ -101,21 +103,24 @@ static int ioremap_try_huge_pmd(pmd_t *pmd, unsigned long addr,
101
103
}
102
104
103
105
static inline int ioremap_pmd_range (pud_t * pud , unsigned long addr ,
104
- unsigned long end , phys_addr_t phys_addr , pgprot_t prot )
106
+ unsigned long end , phys_addr_t phys_addr , pgprot_t prot ,
107
+ pgtbl_mod_mask * mask )
105
108
{
106
109
pmd_t * pmd ;
107
110
unsigned long next ;
108
111
109
- pmd = pmd_alloc (& init_mm , pud , addr );
112
+ pmd = pmd_alloc_track (& init_mm , pud , addr , mask );
110
113
if (!pmd )
111
114
return - ENOMEM ;
112
115
do {
113
116
next = pmd_addr_end (addr , end );
114
117
115
- if (ioremap_try_huge_pmd (pmd , addr , next , phys_addr , prot ))
118
+ if (ioremap_try_huge_pmd (pmd , addr , next , phys_addr , prot )) {
119
+ * mask |= PGTBL_PMD_MODIFIED ;
116
120
continue ;
121
+ }
117
122
118
- if (ioremap_pte_range (pmd , addr , next , phys_addr , prot ))
123
+ if (ioremap_pte_range (pmd , addr , next , phys_addr , prot , mask ))
119
124
return - ENOMEM ;
120
125
} while (pmd ++ , phys_addr += (next - addr ), addr = next , addr != end );
121
126
return 0 ;
@@ -144,21 +149,24 @@ static int ioremap_try_huge_pud(pud_t *pud, unsigned long addr,
144
149
}
145
150
146
151
static inline int ioremap_pud_range (p4d_t * p4d , unsigned long addr ,
147
- unsigned long end , phys_addr_t phys_addr , pgprot_t prot )
152
+ unsigned long end , phys_addr_t phys_addr , pgprot_t prot ,
153
+ pgtbl_mod_mask * mask )
148
154
{
149
155
pud_t * pud ;
150
156
unsigned long next ;
151
157
152
- pud = pud_alloc (& init_mm , p4d , addr );
158
+ pud = pud_alloc_track (& init_mm , p4d , addr , mask );
153
159
if (!pud )
154
160
return - ENOMEM ;
155
161
do {
156
162
next = pud_addr_end (addr , end );
157
163
158
- if (ioremap_try_huge_pud (pud , addr , next , phys_addr , prot ))
164
+ if (ioremap_try_huge_pud (pud , addr , next , phys_addr , prot )) {
165
+ * mask |= PGTBL_PUD_MODIFIED ;
159
166
continue ;
167
+ }
160
168
161
- if (ioremap_pmd_range (pud , addr , next , phys_addr , prot ))
169
+ if (ioremap_pmd_range (pud , addr , next , phys_addr , prot , mask ))
162
170
return - ENOMEM ;
163
171
} while (pud ++ , phys_addr += (next - addr ), addr = next , addr != end );
164
172
return 0 ;
@@ -187,21 +195,24 @@ static int ioremap_try_huge_p4d(p4d_t *p4d, unsigned long addr,
187
195
}
188
196
189
197
static inline int ioremap_p4d_range (pgd_t * pgd , unsigned long addr ,
190
- unsigned long end , phys_addr_t phys_addr , pgprot_t prot )
198
+ unsigned long end , phys_addr_t phys_addr , pgprot_t prot ,
199
+ pgtbl_mod_mask * mask )
191
200
{
192
201
p4d_t * p4d ;
193
202
unsigned long next ;
194
203
195
- p4d = p4d_alloc (& init_mm , pgd , addr );
204
+ p4d = p4d_alloc_track (& init_mm , pgd , addr , mask );
196
205
if (!p4d )
197
206
return - ENOMEM ;
198
207
do {
199
208
next = p4d_addr_end (addr , end );
200
209
201
- if (ioremap_try_huge_p4d (p4d , addr , next , phys_addr , prot ))
210
+ if (ioremap_try_huge_p4d (p4d , addr , next , phys_addr , prot )) {
211
+ * mask |= PGTBL_P4D_MODIFIED ;
202
212
continue ;
213
+ }
203
214
204
- if (ioremap_pud_range (p4d , addr , next , phys_addr , prot ))
215
+ if (ioremap_pud_range (p4d , addr , next , phys_addr , prot , mask ))
205
216
return - ENOMEM ;
206
217
} while (p4d ++ , phys_addr += (next - addr ), addr = next , addr != end );
207
218
return 0 ;
@@ -214,6 +225,7 @@ int ioremap_page_range(unsigned long addr,
214
225
unsigned long start ;
215
226
unsigned long next ;
216
227
int err ;
228
+ pgtbl_mod_mask mask = 0 ;
217
229
218
230
might_sleep ();
219
231
BUG_ON (addr >= end );
@@ -222,13 +234,17 @@ int ioremap_page_range(unsigned long addr,
222
234
pgd = pgd_offset_k (addr );
223
235
do {
224
236
next = pgd_addr_end (addr , end );
225
- err = ioremap_p4d_range (pgd , addr , next , phys_addr , prot );
237
+ err = ioremap_p4d_range (pgd , addr , next , phys_addr , prot ,
238
+ & mask );
226
239
if (err )
227
240
break ;
228
241
} while (pgd ++ , phys_addr += (next - addr ), addr = next , addr != end );
229
242
230
243
flush_cache_vmap (start , end );
231
244
245
+ if (mask & ARCH_PAGE_TABLE_SYNC_MASK )
246
+ arch_sync_kernel_mappings (start , end );
247
+
232
248
return err ;
233
249
}
234
250
0 commit comments