Commit 7e12284c authored by Heiko Carstens's avatar Heiko Carstens Committed by Vasily Gorbik

s390/mm/ptdump: Improve sorting of markers

Use the sort() from lib/sort.c to sort markers instead of the private
implementation. The current implementation does not sort markers
properly if they have to be moved downwards:

---[ Real Memory Copy Area Start ]---
0x0000035b903ff000-0x0000035b90400000         4K PTE I
---[ vmalloc Area Start ]---
---[ Real Memory Copy Area End ]---

Add a new member to each marker which indicates if a marker is start
of an area. If addresses of areas are equal consider an address which
defines the start of an area higher than the address which defines the
end of an area. In result the output is sorted as intended:

---[ Real Memory Copy Area Start ]---
0x0000019cedcff000-0x0000019cedd00000         4K PTE I
---[ Real Memory Copy Area End ]---
---[ vmalloc Area Start ]---
Reviewed-by: default avatarAlexander Gordeev <agordeev@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent 7e4d4cfe
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <linux/ptdump.h> #include <linux/ptdump.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/sort.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/kfence.h> #include <linux/kfence.h>
#include <linux/kasan.h> #include <linux/kasan.h>
...@@ -15,6 +16,7 @@ ...@@ -15,6 +16,7 @@
static unsigned long max_addr; static unsigned long max_addr;
struct addr_marker { struct addr_marker {
int is_start;
unsigned long start_address; unsigned long start_address;
const char *name; const char *name;
}; };
...@@ -60,44 +62,44 @@ enum address_markers_idx { ...@@ -60,44 +62,44 @@ enum address_markers_idx {
}; };
static struct addr_marker address_markers[] = { static struct addr_marker address_markers[] = {
[KVA_NR] = {0, "Kernel Virtual Address Space"}, [KVA_NR] = {0, 0, "Kernel Virtual Address Space"},
[LOWCORE_START_NR] = {0, "Lowcore Start"}, [LOWCORE_START_NR] = {1, 0, "Lowcore Start"},
[LOWCORE_END_NR] = {0, "Lowcore End"}, [LOWCORE_END_NR] = {0, 0, "Lowcore End"},
[IDENTITY_START_NR] = {0, "Identity Mapping Start"}, [IDENTITY_START_NR] = {1, 0, "Identity Mapping Start"},
[IDENTITY_END_NR] = {0, "Identity Mapping End"}, [IDENTITY_END_NR] = {0, 0, "Identity Mapping End"},
[AMODE31_START_NR] = {0, "Amode31 Area Start"}, [AMODE31_START_NR] = {1, 0, "Amode31 Area Start"},
[AMODE31_END_NR] = {0, "Amode31 Area End"}, [AMODE31_END_NR] = {0, 0, "Amode31 Area End"},
[KERNEL_START_NR] = {(unsigned long)_stext, "Kernel Image Start"}, [KERNEL_START_NR] = {1, (unsigned long)_stext, "Kernel Image Start"},
[KERNEL_END_NR] = {(unsigned long)_end, "Kernel Image End"}, [KERNEL_END_NR] = {0, (unsigned long)_end, "Kernel Image End"},
#ifdef CONFIG_KFENCE #ifdef CONFIG_KFENCE
[KFENCE_START_NR] = {0, "KFence Pool Start"}, [KFENCE_START_NR] = {1, 0, "KFence Pool Start"},
[KFENCE_END_NR] = {0, "KFence Pool End"}, [KFENCE_END_NR] = {0, 0, "KFence Pool End"},
#endif #endif
[VMEMMAP_NR] = {0, "vmemmap Area Start"}, [VMEMMAP_NR] = {1, 0, "vmemmap Area Start"},
[VMEMMAP_END_NR] = {0, "vmemmap Area End"}, [VMEMMAP_END_NR] = {0, 0, "vmemmap Area End"},
[VMALLOC_NR] = {0, "vmalloc Area Start"}, [VMALLOC_NR] = {1, 0, "vmalloc Area Start"},
[VMALLOC_END_NR] = {0, "vmalloc Area End"}, [VMALLOC_END_NR] = {0, 0, "vmalloc Area End"},
#ifdef CONFIG_KMSAN #ifdef CONFIG_KMSAN
[KMSAN_VMALLOC_SHADOW_START_NR] = {0, "Kmsan vmalloc Shadow Start"}, [KMSAN_VMALLOC_SHADOW_START_NR] = {1, 0, "Kmsan vmalloc Shadow Start"},
[KMSAN_VMALLOC_SHADOW_END_NR] = {0, "Kmsan vmalloc Shadow End"}, [KMSAN_VMALLOC_SHADOW_END_NR] = {0, 0, "Kmsan vmalloc Shadow End"},
[KMSAN_VMALLOC_ORIGIN_START_NR] = {0, "Kmsan vmalloc Origins Start"}, [KMSAN_VMALLOC_ORIGIN_START_NR] = {1, 0, "Kmsan vmalloc Origins Start"},
[KMSAN_VMALLOC_ORIGIN_END_NR] = {0, "Kmsan vmalloc Origins End"}, [KMSAN_VMALLOC_ORIGIN_END_NR] = {0, 0, "Kmsan vmalloc Origins End"},
[KMSAN_MODULES_SHADOW_START_NR] = {0, "Kmsan Modules Shadow Start"}, [KMSAN_MODULES_SHADOW_START_NR] = {1, 0, "Kmsan Modules Shadow Start"},
[KMSAN_MODULES_SHADOW_END_NR] = {0, "Kmsan Modules Shadow End"}, [KMSAN_MODULES_SHADOW_END_NR] = {0, 0, "Kmsan Modules Shadow End"},
[KMSAN_MODULES_ORIGIN_START_NR] = {0, "Kmsan Modules Origins Start"}, [KMSAN_MODULES_ORIGIN_START_NR] = {1, 0, "Kmsan Modules Origins Start"},
[KMSAN_MODULES_ORIGIN_END_NR] = {0, "Kmsan Modules Origins End"}, [KMSAN_MODULES_ORIGIN_END_NR] = {0, 0, "Kmsan Modules Origins End"},
#endif #endif
[MODULES_NR] = {0, "Modules Area Start"}, [MODULES_NR] = {1, 0, "Modules Area Start"},
[MODULES_END_NR] = {0, "Modules Area End"}, [MODULES_END_NR] = {0, 0, "Modules Area End"},
[ABS_LOWCORE_NR] = {0, "Lowcore Area Start"}, [ABS_LOWCORE_NR] = {1, 0, "Lowcore Area Start"},
[ABS_LOWCORE_END_NR] = {0, "Lowcore Area End"}, [ABS_LOWCORE_END_NR] = {0, 0, "Lowcore Area End"},
[MEMCPY_REAL_NR] = {0, "Real Memory Copy Area Start"}, [MEMCPY_REAL_NR] = {1, 0, "Real Memory Copy Area Start"},
[MEMCPY_REAL_END_NR] = {0, "Real Memory Copy Area End"}, [MEMCPY_REAL_END_NR] = {0, 0, "Real Memory Copy Area End"},
#ifdef CONFIG_KASAN #ifdef CONFIG_KASAN
[KASAN_SHADOW_START_NR] = {KASAN_SHADOW_START, "Kasan Shadow Start"}, [KASAN_SHADOW_START_NR] = {1, KASAN_SHADOW_START, "Kasan Shadow Start"},
[KASAN_SHADOW_END_NR] = {KASAN_SHADOW_END, "Kasan Shadow End"}, [KASAN_SHADOW_END_NR] = {0, KASAN_SHADOW_END, "Kasan Shadow End"},
#endif #endif
{ -1, NULL } {1, -1UL, NULL}
}; };
struct pg_state { struct pg_state {
...@@ -287,22 +289,25 @@ static int ptdump_show(struct seq_file *m, void *v) ...@@ -287,22 +289,25 @@ static int ptdump_show(struct seq_file *m, void *v)
DEFINE_SHOW_ATTRIBUTE(ptdump); DEFINE_SHOW_ATTRIBUTE(ptdump);
#endif /* CONFIG_PTDUMP_DEBUGFS */ #endif /* CONFIG_PTDUMP_DEBUGFS */
/* static int ptdump_cmp(const void *a, const void *b)
* Heapsort from lib/sort.c is not a stable sorting algorithm, do a simple
* insertion sort to preserve the original order of markers with the same
* start address.
*/
static void sort_address_markers(void)
{ {
struct addr_marker tmp; const struct addr_marker *ama = a;
int i, j; const struct addr_marker *amb = b;
for (i = 1; i < ARRAY_SIZE(address_markers) - 1; i++) { if (ama->start_address > amb->start_address)
tmp = address_markers[i]; return 1;
for (j = i - 1; j >= 0 && address_markers[j].start_address > tmp.start_address; j--) if (ama->start_address < amb->start_address)
address_markers[j + 1] = address_markers[j]; return -1;
address_markers[j + 1] = tmp; /*
} * If the start addresses of two markers are identical consider the
* marker which defines the start of an area higher than the one which
* defines the end of an area. This keeps pairs of markers sorted.
*/
if (ama->is_start)
return 1;
if (amb->is_start)
return -1;
return 0;
} }
static int pt_dump_init(void) static int pt_dump_init(void)
...@@ -349,7 +354,8 @@ static int pt_dump_init(void) ...@@ -349,7 +354,8 @@ static int pt_dump_init(void)
address_markers[KMSAN_MODULES_ORIGIN_START_NR].start_address = KMSAN_MODULES_ORIGIN_START; address_markers[KMSAN_MODULES_ORIGIN_START_NR].start_address = KMSAN_MODULES_ORIGIN_START;
address_markers[KMSAN_MODULES_ORIGIN_END_NR].start_address = KMSAN_MODULES_ORIGIN_END; address_markers[KMSAN_MODULES_ORIGIN_END_NR].start_address = KMSAN_MODULES_ORIGIN_END;
#endif #endif
sort_address_markers(); sort(address_markers, ARRAY_SIZE(address_markers) - 1,
sizeof(address_markers[0]), ptdump_cmp, NULL);
#ifdef CONFIG_PTDUMP_DEBUGFS #ifdef CONFIG_PTDUMP_DEBUGFS
debugfs_create_file("kernel_page_tables", 0400, NULL, NULL, &ptdump_fops); debugfs_create_file("kernel_page_tables", 0400, NULL, NULL, &ptdump_fops);
#endif /* CONFIG_PTDUMP_DEBUGFS */ #endif /* CONFIG_PTDUMP_DEBUGFS */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment