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); |