16
16
#include <linux/io.h>
17
17
#include <linux/mm.h>
18
18
#include <linux/highmem.h>
19
+ #include <linux/ptdump.h>
19
20
#include <linux/sched.h>
20
21
#include <linux/seq_file.h>
21
22
#include <asm/fixmap.h>
54
55
*
55
56
*/
56
57
struct pg_state {
58
+ struct ptdump_state ptdump ;
57
59
struct seq_file * seq ;
58
60
const struct addr_marker * marker ;
59
61
unsigned long start_address ;
@@ -102,6 +104,11 @@ static struct addr_marker address_markers[] = {
102
104
{ -1 , NULL },
103
105
};
104
106
107
+ static struct ptdump_range ptdump_range [] __ro_after_init = {
108
+ {TASK_SIZE_MAX , ~0UL },
109
+ {0 , 0 }
110
+ };
111
+
105
112
#define pt_dump_seq_printf (m , fmt , args ...) \
106
113
({ \
107
114
if (m) \
@@ -204,10 +211,10 @@ static void note_page_update_state(struct pg_state *st, unsigned long addr, int
204
211
}
205
212
}
206
213
207
- static void note_page (struct pg_state * st , unsigned long addr ,
208
- int level , u64 val , unsigned long page_size )
214
+ static void note_page (struct ptdump_state * pt_st , unsigned long addr , int level , u64 val )
209
215
{
210
216
u64 flag = level >= 0 ? val & pg_level [level ].mask : 0 ;
217
+ struct pg_state * st = container_of (pt_st , struct pg_state , ptdump );
211
218
212
219
/* At first no level is set */
213
220
if (st -> level == -1 ) {
@@ -245,94 +252,6 @@ static void note_page(struct pg_state *st, unsigned long addr,
245
252
}
246
253
}
247
254
248
- static void walk_pte (struct pg_state * st , pmd_t * pmd , unsigned long start )
249
- {
250
- pte_t * pte = pte_offset_kernel (pmd , 0 );
251
- unsigned long addr ;
252
- unsigned int i ;
253
-
254
- for (i = 0 ; i < PTRS_PER_PTE ; i ++ , pte ++ ) {
255
- addr = start + i * PAGE_SIZE ;
256
- note_page (st , addr , 4 , pte_val (* pte ), PAGE_SIZE );
257
-
258
- }
259
- }
260
-
261
- static void walk_hugepd (struct pg_state * st , hugepd_t * phpd , unsigned long start ,
262
- int pdshift , int level )
263
- {
264
- #ifdef CONFIG_ARCH_HAS_HUGEPD
265
- unsigned int i ;
266
- int shift = hugepd_shift (* phpd );
267
- int ptrs_per_hpd = pdshift - shift > 0 ? 1 << (pdshift - shift ) : 1 ;
268
-
269
- if (start & ((1 << shift ) - 1 ))
270
- return ;
271
-
272
- for (i = 0 ; i < ptrs_per_hpd ; i ++ ) {
273
- unsigned long addr = start + (i << shift );
274
- pte_t * pte = hugepte_offset (* phpd , addr , pdshift );
275
-
276
- note_page (st , addr , level + 1 , pte_val (* pte ), 1 << shift );
277
- }
278
- #endif
279
- }
280
-
281
- static void walk_pmd (struct pg_state * st , pud_t * pud , unsigned long start )
282
- {
283
- pmd_t * pmd = pmd_offset (pud , 0 );
284
- unsigned long addr ;
285
- unsigned int i ;
286
-
287
- for (i = 0 ; i < PTRS_PER_PMD ; i ++ , pmd ++ ) {
288
- addr = start + i * PMD_SIZE ;
289
- if (!pmd_none (* pmd ) && !pmd_is_leaf (* pmd ))
290
- /* pmd exists */
291
- walk_pte (st , pmd , addr );
292
- else
293
- note_page (st , addr , 3 , pmd_val (* pmd ), PMD_SIZE );
294
- }
295
- }
296
-
297
- static void walk_pud (struct pg_state * st , p4d_t * p4d , unsigned long start )
298
- {
299
- pud_t * pud = pud_offset (p4d , 0 );
300
- unsigned long addr ;
301
- unsigned int i ;
302
-
303
- for (i = 0 ; i < PTRS_PER_PUD ; i ++ , pud ++ ) {
304
- addr = start + i * PUD_SIZE ;
305
- if (!pud_none (* pud ) && !pud_is_leaf (* pud ))
306
- /* pud exists */
307
- walk_pmd (st , pud , addr );
308
- else
309
- note_page (st , addr , 2 , pud_val (* pud ), PUD_SIZE );
310
- }
311
- }
312
-
313
- static void walk_pagetables (struct pg_state * st )
314
- {
315
- unsigned int i ;
316
- unsigned long addr = st -> start_address & PGDIR_MASK ;
317
- pgd_t * pgd = pgd_offset_k (addr );
318
-
319
- /*
320
- * Traverse the linux pagetable structure and dump pages that are in
321
- * the hash pagetable.
322
- */
323
- for (i = pgd_index (addr ); i < PTRS_PER_PGD ; i ++ , pgd ++ , addr += PGDIR_SIZE ) {
324
- p4d_t * p4d = p4d_offset (pgd , 0 );
325
-
326
- if (p4d_none (* p4d ) || p4d_is_leaf (* p4d ))
327
- note_page (st , addr , 1 , p4d_val (* p4d ), PGDIR_SIZE );
328
- else if (is_hugepd (__hugepd (p4d_val (* p4d ))))
329
- walk_hugepd (st , (hugepd_t * )p4d , addr , PGDIR_SHIFT , 1 );
330
- else
331
- /* p4d exists */
332
- walk_pud (st , p4d , addr );
333
- }
334
- }
335
-
336
255
static void populate_markers (void )
337
256
{
338
257
int i = 0 ;
@@ -383,17 +302,14 @@ static int ptdump_show(struct seq_file *m, void *v)
383
302
.seq = m ,
384
303
.marker = address_markers ,
385
304
.level = -1 ,
386
- .start_address = IS_ENABLED (CONFIG_PPC64 ) ? PAGE_OFFSET : TASK_SIZE ,
305
+ .ptdump = {
306
+ .note_page = note_page ,
307
+ .range = ptdump_range ,
308
+ }
387
309
};
388
310
389
- #ifdef CONFIG_PPC64
390
- if (!radix_enabled ())
391
- st .start_address = KERN_VIRT_START ;
392
- #endif
393
-
394
311
/* Traverse kernel page tables */
395
- walk_pagetables (& st );
396
- note_page (& st , 0 , -1 , 0 , 0 );
312
+ ptdump_walk_pgd (& st .ptdump , & init_mm , NULL );
397
313
return 0 ;
398
314
}
399
315
@@ -409,23 +325,24 @@ static void build_pgtable_complete_mask(void)
409
325
pg_level [i ].mask |= pg_level [i ].flag [j ].mask ;
410
326
}
411
327
412
- #ifdef CONFIG_PPC_DEBUG_WX
328
+ #ifdef CONFIG_DEBUG_WX
413
329
void ptdump_check_wx (void )
414
330
{
415
331
struct pg_state st = {
416
332
.seq = NULL ,
417
- .marker = address_markers ,
333
+ .marker = (struct addr_marker []) {
334
+ { 0 , NULL },
335
+ { -1 , NULL },
336
+ },
418
337
.level = -1 ,
419
338
.check_wx = true,
420
- .start_address = IS_ENABLED (CONFIG_PPC64 ) ? PAGE_OFFSET : TASK_SIZE ,
339
+ .ptdump = {
340
+ .note_page = note_page ,
341
+ .range = ptdump_range ,
342
+ }
421
343
};
422
344
423
- #ifdef CONFIG_PPC64
424
- if (!radix_enabled ())
425
- st .start_address = KERN_VIRT_START ;
426
- #endif
427
-
428
- walk_pagetables (& st );
345
+ ptdump_walk_pgd (& st .ptdump , & init_mm , NULL );
429
346
430
347
if (st .wx_pages )
431
348
pr_warn ("Checked W+X mappings: FAILED, %lu W+X pages found\n" ,
@@ -435,12 +352,21 @@ void ptdump_check_wx(void)
435
352
}
436
353
#endif
437
354
438
- static int ptdump_init (void )
355
+ static int __init ptdump_init (void )
439
356
{
357
+ #ifdef CONFIG_PPC64
358
+ if (!radix_enabled ())
359
+ ptdump_range [0 ].start = KERN_VIRT_START ;
360
+ else
361
+ ptdump_range [0 ].start = PAGE_OFFSET ;
362
+ #endif
363
+
440
364
populate_markers ();
441
365
build_pgtable_complete_mask ();
442
- debugfs_create_file ("kernel_page_tables" , 0400 , NULL , NULL ,
443
- & ptdump_fops );
366
+
367
+ if (IS_ENABLED (CONFIG_PTDUMP_DEBUGFS ))
368
+ debugfs_create_file ("kernel_page_tables" , 0400 , NULL , NULL , & ptdump_fops );
369
+
444
370
return 0 ;
445
371
}
446
372
device_initcall (ptdump_init );
0 commit comments