GNU Linux-libre 4.14.294-gnu1
[releases.git] / arch / x86 / mm / debug_pagetables.c
1 #include <linux/debugfs.h>
2 #include <linux/module.h>
3 #include <linux/seq_file.h>
4 #include <asm/pgtable.h>
5
6 static int ptdump_show(struct seq_file *m, void *v)
7 {
8         ptdump_walk_pgd_level_debugfs(m, NULL, false);
9         return 0;
10 }
11
12 static int ptdump_open(struct inode *inode, struct file *filp)
13 {
14         return single_open(filp, ptdump_show, NULL);
15 }
16
17 static const struct file_operations ptdump_fops = {
18         .owner          = THIS_MODULE,
19         .open           = ptdump_open,
20         .read           = seq_read,
21         .llseek         = seq_lseek,
22         .release        = single_release,
23 };
24
25 static int ptdump_show_curknl(struct seq_file *m, void *v)
26 {
27         if (current->mm->pgd) {
28                 down_read(&current->mm->mmap_sem);
29                 ptdump_walk_pgd_level_debugfs(m, current->mm->pgd, false);
30                 up_read(&current->mm->mmap_sem);
31         }
32         return 0;
33 }
34
35 static int ptdump_open_curknl(struct inode *inode, struct file *filp)
36 {
37         return single_open(filp, ptdump_show_curknl, NULL);
38 }
39
40 static const struct file_operations ptdump_curknl_fops = {
41         .owner          = THIS_MODULE,
42         .open           = ptdump_open_curknl,
43         .read           = seq_read,
44         .llseek         = seq_lseek,
45         .release        = single_release,
46 };
47
48 #ifdef CONFIG_PAGE_TABLE_ISOLATION
49 static struct dentry *pe_curusr;
50
51 static int ptdump_show_curusr(struct seq_file *m, void *v)
52 {
53         if (current->mm->pgd) {
54                 down_read(&current->mm->mmap_sem);
55                 ptdump_walk_pgd_level_debugfs(m, current->mm->pgd, true);
56                 up_read(&current->mm->mmap_sem);
57         }
58         return 0;
59 }
60
61 static int ptdump_open_curusr(struct inode *inode, struct file *filp)
62 {
63         return single_open(filp, ptdump_show_curusr, NULL);
64 }
65
66 static const struct file_operations ptdump_curusr_fops = {
67         .owner          = THIS_MODULE,
68         .open           = ptdump_open_curusr,
69         .read           = seq_read,
70         .llseek         = seq_lseek,
71         .release        = single_release,
72 };
73 #endif
74
75 static struct dentry *dir, *pe_knl, *pe_curknl;
76
77 static int __init pt_dump_debug_init(void)
78 {
79         dir = debugfs_create_dir("page_tables", NULL);
80         if (!dir)
81                 return -ENOMEM;
82
83         pe_knl = debugfs_create_file("kernel", 0400, dir, NULL,
84                                      &ptdump_fops);
85         if (!pe_knl)
86                 goto err;
87
88         pe_curknl = debugfs_create_file("current_kernel", 0400,
89                                         dir, NULL, &ptdump_curknl_fops);
90         if (!pe_curknl)
91                 goto err;
92
93 #ifdef CONFIG_PAGE_TABLE_ISOLATION
94         pe_curusr = debugfs_create_file("current_user", 0400,
95                                         dir, NULL, &ptdump_curusr_fops);
96         if (!pe_curusr)
97                 goto err;
98 #endif
99         return 0;
100 err:
101         debugfs_remove_recursive(dir);
102         return -ENOMEM;
103 }
104
105 static void __exit pt_dump_debug_exit(void)
106 {
107         debugfs_remove_recursive(dir);
108 }
109
110 module_init(pt_dump_debug_init);
111 module_exit(pt_dump_debug_exit);
112 MODULE_LICENSE("GPL");
113 MODULE_AUTHOR("Arjan van de Ven <arjan@linux.intel.com>");
114 MODULE_DESCRIPTION("Kernel debugging helper that dumps pagetables");