ptdump.c (ead5d1f4d877e92c051e1a1ade623d0d30e71619) ptdump.c (de22d2107ced3cc5355cc9dbbd85e44183546bd5)
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (C) 2019 SiFive
4 */
5
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (C) 2019 SiFive
4 */
5
6#include <linux/efi.h>
6#include <linux/init.h>
7#include <linux/debugfs.h>
8#include <linux/seq_file.h>
9#include <linux/ptdump.h>
10
11#include <asm/ptdump.h>
12#include <linux/pgtable.h>
13#include <asm/kasan.h>

--- 30 unchanged lines hidden (view full) ---

44};
45
46/* Address marker */
47struct addr_marker {
48 unsigned long start_address;
49 const char *name;
50};
51
7#include <linux/init.h>
8#include <linux/debugfs.h>
9#include <linux/seq_file.h>
10#include <linux/ptdump.h>
11
12#include <asm/ptdump.h>
13#include <linux/pgtable.h>
14#include <asm/kasan.h>

--- 30 unchanged lines hidden (view full) ---

45};
46
47/* Address marker */
48struct addr_marker {
49 unsigned long start_address;
50 const char *name;
51};
52
53/* Private information for debugfs */
54struct ptd_mm_info {
55 struct mm_struct *mm;
56 const struct addr_marker *markers;
57 unsigned long base_addr;
58 unsigned long end;
59};
60
52static struct addr_marker address_markers[] = {
53#ifdef CONFIG_KASAN
54 {KASAN_SHADOW_START, "Kasan shadow start"},
55 {KASAN_SHADOW_END, "Kasan shadow end"},
56#endif
57 {FIXADDR_START, "Fixmap start"},
58 {FIXADDR_TOP, "Fixmap end"},
59 {PCI_IO_START, "PCI I/O start"},
60 {PCI_IO_END, "PCI I/O end"},
61#ifdef CONFIG_SPARSEMEM_VMEMMAP
62 {VMEMMAP_START, "vmemmap start"},
63 {VMEMMAP_END, "vmemmap end"},
64#endif
65 {VMALLOC_START, "vmalloc() area"},
66 {VMALLOC_END, "vmalloc() end"},
67 {PAGE_OFFSET, "Linear mapping"},
68 {-1, NULL},
69};
70
61static struct addr_marker address_markers[] = {
62#ifdef CONFIG_KASAN
63 {KASAN_SHADOW_START, "Kasan shadow start"},
64 {KASAN_SHADOW_END, "Kasan shadow end"},
65#endif
66 {FIXADDR_START, "Fixmap start"},
67 {FIXADDR_TOP, "Fixmap end"},
68 {PCI_IO_START, "PCI I/O start"},
69 {PCI_IO_END, "PCI I/O end"},
70#ifdef CONFIG_SPARSEMEM_VMEMMAP
71 {VMEMMAP_START, "vmemmap start"},
72 {VMEMMAP_END, "vmemmap end"},
73#endif
74 {VMALLOC_START, "vmalloc() area"},
75 {VMALLOC_END, "vmalloc() end"},
76 {PAGE_OFFSET, "Linear mapping"},
77 {-1, NULL},
78};
79
80static struct ptd_mm_info kernel_ptd_info = {
81 .mm = &init_mm,
82 .markers = address_markers,
83 .base_addr = KERN_VIRT_START,
84 .end = ULONG_MAX,
85};
86
87#ifdef CONFIG_EFI
88static struct addr_marker efi_addr_markers[] = {
89 { 0, "UEFI runtime start" },
90 { SZ_1G, "UEFI runtime end" },
91 { -1, NULL }
92};
93
94static struct ptd_mm_info efi_ptd_info = {
95 .mm = &efi_mm,
96 .markers = efi_addr_markers,
97 .base_addr = 0,
98 .end = SZ_2G,
99};
100#endif
101
71/* Page Table Entry */
72struct prot_bits {
73 u64 mask;
74 u64 val;
75 const char *set;
76 const char *clear;
77};
78

--- 161 unchanged lines hidden (view full) ---

240 st->last_pa = pa;
241 st->current_prot = prot;
242 st->level = level;
243 } else {
244 st->last_pa = pa;
245 }
246}
247
102/* Page Table Entry */
103struct prot_bits {
104 u64 mask;
105 u64 val;
106 const char *set;
107 const char *clear;
108};
109

--- 161 unchanged lines hidden (view full) ---

271 st->last_pa = pa;
272 st->current_prot = prot;
273 st->level = level;
274 } else {
275 st->last_pa = pa;
276 }
277}
278
248static void ptdump_walk(struct seq_file *s)
279static void ptdump_walk(struct seq_file *s, struct ptd_mm_info *pinfo)
249{
250 struct pg_state st = {
251 .seq = s,
280{
281 struct pg_state st = {
282 .seq = s,
252 .marker = address_markers,
283 .marker = pinfo->markers,
253 .level = -1,
254 .ptdump = {
255 .note_page = note_page,
256 .range = (struct ptdump_range[]) {
284 .level = -1,
285 .ptdump = {
286 .note_page = note_page,
287 .range = (struct ptdump_range[]) {
257 {KERN_VIRT_START, ULONG_MAX},
288 {pinfo->base_addr, pinfo->end},
258 {0, 0}
259 }
260 }
261 };
262
289 {0, 0}
290 }
291 }
292 };
293
263 ptdump_walk_pgd(&st.ptdump, &init_mm, NULL);
294 ptdump_walk_pgd(&st.ptdump, pinfo->mm, NULL);
264}
265
266void ptdump_check_wx(void)
267{
268 struct pg_state st = {
269 .seq = NULL,
270 .marker = (struct addr_marker[]) {
271 {0, NULL},

--- 16 unchanged lines hidden (view full) ---

288 pr_warn("Checked W+X mappings: failed, %lu W+X pages found\n",
289 st.wx_pages);
290 else
291 pr_info("Checked W+X mappings: passed, no W+X pages found\n");
292}
293
294static int ptdump_show(struct seq_file *m, void *v)
295{
295}
296
297void ptdump_check_wx(void)
298{
299 struct pg_state st = {
300 .seq = NULL,
301 .marker = (struct addr_marker[]) {
302 {0, NULL},

--- 16 unchanged lines hidden (view full) ---

319 pr_warn("Checked W+X mappings: failed, %lu W+X pages found\n",
320 st.wx_pages);
321 else
322 pr_info("Checked W+X mappings: passed, no W+X pages found\n");
323}
324
325static int ptdump_show(struct seq_file *m, void *v)
326{
296 ptdump_walk(m);
327 ptdump_walk(m, m->private);
297
298 return 0;
299}
300
301DEFINE_SHOW_ATTRIBUTE(ptdump);
302
303static int ptdump_init(void)
304{
305 unsigned int i, j;
306
307 for (i = 0; i < ARRAY_SIZE(pg_level); i++)
308 for (j = 0; j < ARRAY_SIZE(pte_bits); j++)
309 pg_level[i].mask |= pte_bits[j].mask;
310
328
329 return 0;
330}
331
332DEFINE_SHOW_ATTRIBUTE(ptdump);
333
334static int ptdump_init(void)
335{
336 unsigned int i, j;
337
338 for (i = 0; i < ARRAY_SIZE(pg_level); i++)
339 for (j = 0; j < ARRAY_SIZE(pte_bits); j++)
340 pg_level[i].mask |= pte_bits[j].mask;
341
311 debugfs_create_file("kernel_page_tables", 0400, NULL, NULL,
342 debugfs_create_file("kernel_page_tables", 0400, NULL, &kernel_ptd_info,
312 &ptdump_fops);
343 &ptdump_fops);
344#ifdef CONFIG_EFI
345 if (efi_enabled(EFI_RUNTIME_SERVICES))
346 debugfs_create_file("efi_page_tables", 0400, NULL, &efi_ptd_info,
347 &ptdump_fops);
348#endif
313
314 return 0;
315}
316
317device_initcall(ptdump_init);
349
350 return 0;
351}
352
353device_initcall(ptdump_init);