|
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