@@ -182,6 +182,14 @@ static void pgd_dtor(pgd_t *pgd)
182
182
*/
183
183
#define PREALLOCATED_PMDS UNSHARED_PTRS_PER_PGD
184
184
185
+ /*
186
+ * We allocate separate PMDs for the kernel part of the user page-table
187
+ * when PTI is enabled. We need them to map the per-process LDT into the
188
+ * user-space page-table.
189
+ */
190
+ #define PREALLOCATED_USER_PMDS (static_cpu_has(X86_FEATURE_PTI) ? \
191
+ KERNEL_PGD_PTRS : 0)
192
+
185
193
void pud_populate (struct mm_struct * mm , pud_t * pudp , pmd_t * pmd )
186
194
{
187
195
paravirt_alloc_pmd (mm , __pa (pmd ) >> PAGE_SHIFT );
@@ -202,22 +210,22 @@ void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd)
202
210
203
211
/* No need to prepopulate any pagetable entries in non-PAE modes. */
204
212
#define PREALLOCATED_PMDS 0
205
-
213
+ #define PREALLOCATED_USER_PMDS 0
206
214
#endif /* CONFIG_X86_PAE */
207
215
208
- static void free_pmds (struct mm_struct * mm , pmd_t * pmds [])
216
+ static void free_pmds (struct mm_struct * mm , pmd_t * pmds [], int count )
209
217
{
210
218
int i ;
211
219
212
- for (i = 0 ; i < PREALLOCATED_PMDS ; i ++ )
220
+ for (i = 0 ; i < count ; i ++ )
213
221
if (pmds [i ]) {
214
222
pgtable_pmd_page_dtor (virt_to_page (pmds [i ]));
215
223
free_page ((unsigned long )pmds [i ]);
216
224
mm_dec_nr_pmds (mm );
217
225
}
218
226
}
219
227
220
- static int preallocate_pmds (struct mm_struct * mm , pmd_t * pmds [])
228
+ static int preallocate_pmds (struct mm_struct * mm , pmd_t * pmds [], int count )
221
229
{
222
230
int i ;
223
231
bool failed = false;
@@ -226,7 +234,7 @@ static int preallocate_pmds(struct mm_struct *mm, pmd_t *pmds[])
226
234
if (mm == & init_mm )
227
235
gfp &= ~__GFP_ACCOUNT ;
228
236
229
- for (i = 0 ; i < PREALLOCATED_PMDS ; i ++ ) {
237
+ for (i = 0 ; i < count ; i ++ ) {
230
238
pmd_t * pmd = (pmd_t * )__get_free_page (gfp );
231
239
if (!pmd )
232
240
failed = true;
@@ -241,7 +249,7 @@ static int preallocate_pmds(struct mm_struct *mm, pmd_t *pmds[])
241
249
}
242
250
243
251
if (failed ) {
244
- free_pmds (mm , pmds );
252
+ free_pmds (mm , pmds , count );
245
253
return - ENOMEM ;
246
254
}
247
255
@@ -254,23 +262,38 @@ static int preallocate_pmds(struct mm_struct *mm, pmd_t *pmds[])
254
262
* preallocate which never got a corresponding vma will need to be
255
263
* freed manually.
256
264
*/
265
+ static void mop_up_one_pmd (struct mm_struct * mm , pgd_t * pgdp )
266
+ {
267
+ pgd_t pgd = * pgdp ;
268
+
269
+ if (pgd_val (pgd ) != 0 ) {
270
+ pmd_t * pmd = (pmd_t * )pgd_page_vaddr (pgd );
271
+
272
+ * pgdp = native_make_pgd (0 );
273
+
274
+ paravirt_release_pmd (pgd_val (pgd ) >> PAGE_SHIFT );
275
+ pmd_free (mm , pmd );
276
+ mm_dec_nr_pmds (mm );
277
+ }
278
+ }
279
+
257
280
static void pgd_mop_up_pmds (struct mm_struct * mm , pgd_t * pgdp )
258
281
{
259
282
int i ;
260
283
261
- for (i = 0 ; i < PREALLOCATED_PMDS ; i ++ ) {
262
- pgd_t pgd = pgdp [i ];
284
+ for (i = 0 ; i < PREALLOCATED_PMDS ; i ++ )
285
+ mop_up_one_pmd ( mm , & pgdp [i ]) ;
263
286
264
- if (pgd_val (pgd ) != 0 ) {
265
- pmd_t * pmd = (pmd_t * )pgd_page_vaddr (pgd );
287
+ #ifdef CONFIG_PAGE_TABLE_ISOLATION
266
288
267
- pgdp [i ] = native_make_pgd (0 );
289
+ if (!static_cpu_has (X86_FEATURE_PTI ))
290
+ return ;
268
291
269
- paravirt_release_pmd ( pgd_val ( pgd ) >> PAGE_SHIFT );
270
- pmd_free ( mm , pmd );
271
- mm_dec_nr_pmds ( mm );
272
- }
273
- }
292
+ pgdp = kernel_to_user_pgdp ( pgdp );
293
+
294
+ for ( i = 0 ; i < PREALLOCATED_USER_PMDS ; i ++ )
295
+ mop_up_one_pmd ( mm , & pgdp [ i + KERNEL_PGD_BOUNDARY ]);
296
+ #endif
274
297
}
275
298
276
299
static void pgd_prepopulate_pmd (struct mm_struct * mm , pgd_t * pgd , pmd_t * pmds [])
@@ -296,6 +319,38 @@ static void pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmds[])
296
319
}
297
320
}
298
321
322
+ #ifdef CONFIG_PAGE_TABLE_ISOLATION
323
+ static void pgd_prepopulate_user_pmd (struct mm_struct * mm ,
324
+ pgd_t * k_pgd , pmd_t * pmds [])
325
+ {
326
+ pgd_t * s_pgd = kernel_to_user_pgdp (swapper_pg_dir );
327
+ pgd_t * u_pgd = kernel_to_user_pgdp (k_pgd );
328
+ p4d_t * u_p4d ;
329
+ pud_t * u_pud ;
330
+ int i ;
331
+
332
+ u_p4d = p4d_offset (u_pgd , 0 );
333
+ u_pud = pud_offset (u_p4d , 0 );
334
+
335
+ s_pgd += KERNEL_PGD_BOUNDARY ;
336
+ u_pud += KERNEL_PGD_BOUNDARY ;
337
+
338
+ for (i = 0 ; i < PREALLOCATED_USER_PMDS ; i ++ , u_pud ++ , s_pgd ++ ) {
339
+ pmd_t * pmd = pmds [i ];
340
+
341
+ memcpy (pmd , (pmd_t * )pgd_page_vaddr (* s_pgd ),
342
+ sizeof (pmd_t ) * PTRS_PER_PMD );
343
+
344
+ pud_populate (mm , u_pud , pmd );
345
+ }
346
+
347
+ }
348
+ #else
349
+ static void pgd_prepopulate_user_pmd (struct mm_struct * mm ,
350
+ pgd_t * k_pgd , pmd_t * pmds [])
351
+ {
352
+ }
353
+ #endif
299
354
/*
300
355
* Xen paravirt assumes pgd table should be in one page. 64 bit kernel also
301
356
* assumes that pgd should be in one page.
@@ -376,6 +431,7 @@ static inline void _pgd_free(pgd_t *pgd)
376
431
pgd_t * pgd_alloc (struct mm_struct * mm )
377
432
{
378
433
pgd_t * pgd ;
434
+ pmd_t * u_pmds [PREALLOCATED_USER_PMDS ];
379
435
pmd_t * pmds [PREALLOCATED_PMDS ];
380
436
381
437
pgd = _pgd_alloc ();
@@ -385,12 +441,15 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
385
441
386
442
mm -> pgd = pgd ;
387
443
388
- if (preallocate_pmds (mm , pmds ) != 0 )
444
+ if (preallocate_pmds (mm , pmds , PREALLOCATED_PMDS ) != 0 )
389
445
goto out_free_pgd ;
390
446
391
- if (paravirt_pgd_alloc (mm ) != 0 )
447
+ if (preallocate_pmds (mm , u_pmds , PREALLOCATED_USER_PMDS ) != 0 )
392
448
goto out_free_pmds ;
393
449
450
+ if (paravirt_pgd_alloc (mm ) != 0 )
451
+ goto out_free_user_pmds ;
452
+
394
453
/*
395
454
* Make sure that pre-populating the pmds is atomic with
396
455
* respect to anything walking the pgd_list, so that they
@@ -400,13 +459,16 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
400
459
401
460
pgd_ctor (mm , pgd );
402
461
pgd_prepopulate_pmd (mm , pgd , pmds );
462
+ pgd_prepopulate_user_pmd (mm , pgd , u_pmds );
403
463
404
464
spin_unlock (& pgd_lock );
405
465
406
466
return pgd ;
407
467
468
+ out_free_user_pmds :
469
+ free_pmds (mm , u_pmds , PREALLOCATED_USER_PMDS );
408
470
out_free_pmds :
409
- free_pmds (mm , pmds );
471
+ free_pmds (mm , pmds , PREALLOCATED_PMDS );
410
472
out_free_pgd :
411
473
_pgd_free (pgd );
412
474
out :
0 commit comments