|
3 | 3 | #include <linux/ptdump.h>
|
4 | 4 | #include <linux/seq_file.h>
|
5 | 5 | #include <linux/debugfs.h>
|
| 6 | +#include <linux/sort.h> |
6 | 7 | #include <linux/mm.h>
|
7 | 8 | #include <linux/kfence.h>
|
8 | 9 | #include <linux/kasan.h>
|
|
15 | 16 | static unsigned long max_addr;
|
16 | 17 |
|
17 | 18 | struct addr_marker {
|
| 19 | + int is_start; |
18 | 20 | unsigned long start_address;
|
19 | 21 | const char *name;
|
20 | 22 | };
|
@@ -60,44 +62,44 @@ enum address_markers_idx {
|
60 | 62 | };
|
61 | 63 |
|
62 | 64 | static struct addr_marker address_markers[] = {
|
63 |
| - [KVA_NR] = {0, "Kernel Virtual Address Space"}, |
64 |
| - [LOWCORE_START_NR] = {0, "Lowcore Start"}, |
65 |
| - [LOWCORE_END_NR] = {0, "Lowcore End"}, |
66 |
| - [IDENTITY_START_NR] = {0, "Identity Mapping Start"}, |
67 |
| - [IDENTITY_END_NR] = {0, "Identity Mapping End"}, |
68 |
| - [AMODE31_START_NR] = {0, "Amode31 Area Start"}, |
69 |
| - [AMODE31_END_NR] = {0, "Amode31 Area End"}, |
70 |
| - [KERNEL_START_NR] = {(unsigned long)_stext, "Kernel Image Start"}, |
71 |
| - [KERNEL_END_NR] = {(unsigned long)_end, "Kernel Image End"}, |
| 65 | + [KVA_NR] = {0, 0, "Kernel Virtual Address Space"}, |
| 66 | + [LOWCORE_START_NR] = {1, 0, "Lowcore Start"}, |
| 67 | + [LOWCORE_END_NR] = {0, 0, "Lowcore End"}, |
| 68 | + [IDENTITY_START_NR] = {1, 0, "Identity Mapping Start"}, |
| 69 | + [IDENTITY_END_NR] = {0, 0, "Identity Mapping End"}, |
| 70 | + [AMODE31_START_NR] = {1, 0, "Amode31 Area Start"}, |
| 71 | + [AMODE31_END_NR] = {0, 0, "Amode31 Area End"}, |
| 72 | + [KERNEL_START_NR] = {1, (unsigned long)_stext, "Kernel Image Start"}, |
| 73 | + [KERNEL_END_NR] = {0, (unsigned long)_end, "Kernel Image End"}, |
72 | 74 | #ifdef CONFIG_KFENCE
|
73 |
| - [KFENCE_START_NR] = {0, "KFence Pool Start"}, |
74 |
| - [KFENCE_END_NR] = {0, "KFence Pool End"}, |
| 75 | + [KFENCE_START_NR] = {1, 0, "KFence Pool Start"}, |
| 76 | + [KFENCE_END_NR] = {0, 0, "KFence Pool End"}, |
75 | 77 | #endif
|
76 |
| - [VMEMMAP_NR] = {0, "vmemmap Area Start"}, |
77 |
| - [VMEMMAP_END_NR] = {0, "vmemmap Area End"}, |
78 |
| - [VMALLOC_NR] = {0, "vmalloc Area Start"}, |
79 |
| - [VMALLOC_END_NR] = {0, "vmalloc Area End"}, |
| 78 | + [VMEMMAP_NR] = {1, 0, "vmemmap Area Start"}, |
| 79 | + [VMEMMAP_END_NR] = {0, 0, "vmemmap Area End"}, |
| 80 | + [VMALLOC_NR] = {1, 0, "vmalloc Area Start"}, |
| 81 | + [VMALLOC_END_NR] = {0, 0, "vmalloc Area End"}, |
80 | 82 | #ifdef CONFIG_KMSAN
|
81 |
| - [KMSAN_VMALLOC_SHADOW_START_NR] = {0, "Kmsan vmalloc Shadow Start"}, |
82 |
| - [KMSAN_VMALLOC_SHADOW_END_NR] = {0, "Kmsan vmalloc Shadow End"}, |
83 |
| - [KMSAN_VMALLOC_ORIGIN_START_NR] = {0, "Kmsan vmalloc Origins Start"}, |
84 |
| - [KMSAN_VMALLOC_ORIGIN_END_NR] = {0, "Kmsan vmalloc Origins End"}, |
85 |
| - [KMSAN_MODULES_SHADOW_START_NR] = {0, "Kmsan Modules Shadow Start"}, |
86 |
| - [KMSAN_MODULES_SHADOW_END_NR] = {0, "Kmsan Modules Shadow End"}, |
87 |
| - [KMSAN_MODULES_ORIGIN_START_NR] = {0, "Kmsan Modules Origins Start"}, |
88 |
| - [KMSAN_MODULES_ORIGIN_END_NR] = {0, "Kmsan Modules Origins End"}, |
| 83 | + [KMSAN_VMALLOC_SHADOW_START_NR] = {1, 0, "Kmsan vmalloc Shadow Start"}, |
| 84 | + [KMSAN_VMALLOC_SHADOW_END_NR] = {0, 0, "Kmsan vmalloc Shadow End"}, |
| 85 | + [KMSAN_VMALLOC_ORIGIN_START_NR] = {1, 0, "Kmsan vmalloc Origins Start"}, |
| 86 | + [KMSAN_VMALLOC_ORIGIN_END_NR] = {0, 0, "Kmsan vmalloc Origins End"}, |
| 87 | + [KMSAN_MODULES_SHADOW_START_NR] = {1, 0, "Kmsan Modules Shadow Start"}, |
| 88 | + [KMSAN_MODULES_SHADOW_END_NR] = {0, 0, "Kmsan Modules Shadow End"}, |
| 89 | + [KMSAN_MODULES_ORIGIN_START_NR] = {1, 0, "Kmsan Modules Origins Start"}, |
| 90 | + [KMSAN_MODULES_ORIGIN_END_NR] = {0, 0, "Kmsan Modules Origins End"}, |
89 | 91 | #endif
|
90 |
| - [MODULES_NR] = {0, "Modules Area Start"}, |
91 |
| - [MODULES_END_NR] = {0, "Modules Area End"}, |
92 |
| - [ABS_LOWCORE_NR] = {0, "Lowcore Area Start"}, |
93 |
| - [ABS_LOWCORE_END_NR] = {0, "Lowcore Area End"}, |
94 |
| - [MEMCPY_REAL_NR] = {0, "Real Memory Copy Area Start"}, |
95 |
| - [MEMCPY_REAL_END_NR] = {0, "Real Memory Copy Area End"}, |
| 92 | + [MODULES_NR] = {1, 0, "Modules Area Start"}, |
| 93 | + [MODULES_END_NR] = {0, 0, "Modules Area End"}, |
| 94 | + [ABS_LOWCORE_NR] = {1, 0, "Lowcore Area Start"}, |
| 95 | + [ABS_LOWCORE_END_NR] = {0, 0, "Lowcore Area End"}, |
| 96 | + [MEMCPY_REAL_NR] = {1, 0, "Real Memory Copy Area Start"}, |
| 97 | + [MEMCPY_REAL_END_NR] = {0, 0, "Real Memory Copy Area End"}, |
96 | 98 | #ifdef CONFIG_KASAN
|
97 |
| - [KASAN_SHADOW_START_NR] = {KASAN_SHADOW_START, "Kasan Shadow Start"}, |
98 |
| - [KASAN_SHADOW_END_NR] = {KASAN_SHADOW_END, "Kasan Shadow End"}, |
| 99 | + [KASAN_SHADOW_START_NR] = {1, KASAN_SHADOW_START, "Kasan Shadow Start"}, |
| 100 | + [KASAN_SHADOW_END_NR] = {0, KASAN_SHADOW_END, "Kasan Shadow End"}, |
99 | 101 | #endif
|
100 |
| - { -1, NULL } |
| 102 | + {1, -1UL, NULL} |
101 | 103 | };
|
102 | 104 |
|
103 | 105 | struct pg_state {
|
@@ -287,22 +289,25 @@ static int ptdump_show(struct seq_file *m, void *v)
|
287 | 289 | DEFINE_SHOW_ATTRIBUTE(ptdump);
|
288 | 290 | #endif /* CONFIG_PTDUMP_DEBUGFS */
|
289 | 291 |
|
290 |
| -/* |
291 |
| - * Heapsort from lib/sort.c is not a stable sorting algorithm, do a simple |
292 |
| - * insertion sort to preserve the original order of markers with the same |
293 |
| - * start address. |
294 |
| - */ |
295 |
| -static void sort_address_markers(void) |
| 292 | +static int ptdump_cmp(const void *a, const void *b) |
296 | 293 | {
|
297 |
| - struct addr_marker tmp; |
298 |
| - int i, j; |
| 294 | + const struct addr_marker *ama = a; |
| 295 | + const struct addr_marker *amb = b; |
299 | 296 |
|
300 |
| - for (i = 1; i < ARRAY_SIZE(address_markers) - 1; i++) { |
301 |
| - tmp = address_markers[i]; |
302 |
| - for (j = i - 1; j >= 0 && address_markers[j].start_address > tmp.start_address; j--) |
303 |
| - address_markers[j + 1] = address_markers[j]; |
304 |
| - address_markers[j + 1] = tmp; |
305 |
| - } |
| 297 | + if (ama->start_address > amb->start_address) |
| 298 | + return 1; |
| 299 | + if (ama->start_address < amb->start_address) |
| 300 | + return -1; |
| 301 | + /* |
| 302 | + * If the start addresses of two markers are identical consider the |
| 303 | + * marker which defines the start of an area higher than the one which |
| 304 | + * defines the end of an area. This keeps pairs of markers sorted. |
| 305 | + */ |
| 306 | + if (ama->is_start) |
| 307 | + return 1; |
| 308 | + if (amb->is_start) |
| 309 | + return -1; |
| 310 | + return 0; |
306 | 311 | }
|
307 | 312 |
|
308 | 313 | static int pt_dump_init(void)
|
@@ -349,7 +354,8 @@ static int pt_dump_init(void)
|
349 | 354 | address_markers[KMSAN_MODULES_ORIGIN_START_NR].start_address = KMSAN_MODULES_ORIGIN_START;
|
350 | 355 | address_markers[KMSAN_MODULES_ORIGIN_END_NR].start_address = KMSAN_MODULES_ORIGIN_END;
|
351 | 356 | #endif
|
352 |
| - sort_address_markers(); |
| 357 | + sort(address_markers, ARRAY_SIZE(address_markers) - 1, |
| 358 | + sizeof(address_markers[0]), ptdump_cmp, NULL); |
353 | 359 | #ifdef CONFIG_PTDUMP_DEBUGFS
|
354 | 360 | debugfs_create_file("kernel_page_tables", 0400, NULL, NULL, &ptdump_fops);
|
355 | 361 | #endif /* CONFIG_PTDUMP_DEBUGFS */
|
|
0 commit comments