1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2da1694adSHeiko Carstens #include <linux/set_memory.h> 39d719d39SHeiko Carstens #include <linux/ptdump.h> 4e76e82d7SHeiko Carstens #include <linux/seq_file.h> 5e76e82d7SHeiko Carstens #include <linux/debugfs.h> 6*7e12284cSHeiko Carstens #include <linux/sort.h> 7e76e82d7SHeiko Carstens #include <linux/mm.h> 8d6de72cfSSven Schnelle #include <linux/kfence.h> 9e006222bSVasily Gorbik #include <linux/kasan.h> 100dac8f6bSVasily Gorbik #include <asm/kasan.h> 1150787755SAlexander Gordeev #include <asm/abs_lowcore.h> 123b051e89SSven Schnelle #include <asm/nospec-branch.h> 13e76e82d7SHeiko Carstens #include <asm/sections.h> 14c0ceb944SAlexander Gordeev #include <asm/maccess.h> 15e76e82d7SHeiko Carstens 16e76e82d7SHeiko Carstens static unsigned long max_addr; 17e76e82d7SHeiko Carstens 18e76e82d7SHeiko Carstens struct addr_marker { 19*7e12284cSHeiko Carstens int is_start; 20e76e82d7SHeiko Carstens unsigned long start_address; 21e76e82d7SHeiko Carstens const char *name; 22e76e82d7SHeiko Carstens }; 23e76e82d7SHeiko Carstens 24e76e82d7SHeiko Carstens enum address_markers_idx { 257e4d4cfeSHeiko Carstens KVA_NR = 0, 267e4d4cfeSHeiko Carstens LOWCORE_START_NR, 2737395344SHeiko Carstens LOWCORE_END_NR, 28edcfc9c7SHeiko Carstens AMODE31_START_NR, 29edcfc9c7SHeiko Carstens AMODE31_END_NR, 30e76e82d7SHeiko Carstens KERNEL_START_NR, 31e76e82d7SHeiko Carstens KERNEL_END_NR, 32d6de72cfSSven Schnelle #ifdef CONFIG_KFENCE 33d6de72cfSSven Schnelle KFENCE_START_NR, 34d6de72cfSSven Schnelle KFENCE_END_NR, 35d6de72cfSSven Schnelle #endif 3637395344SHeiko Carstens IDENTITY_START_NR, 3737395344SHeiko Carstens IDENTITY_END_NR, 38e76e82d7SHeiko Carstens VMEMMAP_NR, 39e670e64aSVasily Gorbik VMEMMAP_END_NR, 40e76e82d7SHeiko Carstens VMALLOC_NR, 41e670e64aSVasily Gorbik VMALLOC_END_NR, 4219af2887SIlya Leoshkevich #ifdef CONFIG_KMSAN 4319af2887SIlya Leoshkevich KMSAN_VMALLOC_SHADOW_START_NR, 4419af2887SIlya Leoshkevich KMSAN_VMALLOC_SHADOW_END_NR, 4519af2887SIlya Leoshkevich KMSAN_VMALLOC_ORIGIN_START_NR, 4619af2887SIlya Leoshkevich KMSAN_VMALLOC_ORIGIN_END_NR, 4719af2887SIlya Leoshkevich KMSAN_MODULES_SHADOW_START_NR, 4819af2887SIlya Leoshkevich KMSAN_MODULES_SHADOW_END_NR, 4919af2887SIlya Leoshkevich KMSAN_MODULES_ORIGIN_START_NR, 5019af2887SIlya Leoshkevich KMSAN_MODULES_ORIGIN_END_NR, 5119af2887SIlya Leoshkevich #endif 52c972cc60SHeiko Carstens MODULES_NR, 53e670e64aSVasily Gorbik MODULES_END_NR, 5450787755SAlexander Gordeev ABS_LOWCORE_NR, 5550787755SAlexander Gordeev ABS_LOWCORE_END_NR, 56c0ceb944SAlexander Gordeev MEMCPY_REAL_NR, 57c0ceb944SAlexander Gordeev MEMCPY_REAL_END_NR, 5805178996SVasily Gorbik #ifdef CONFIG_KASAN 5905178996SVasily Gorbik KASAN_SHADOW_START_NR, 6005178996SVasily Gorbik KASAN_SHADOW_END_NR, 6105178996SVasily Gorbik #endif 62e76e82d7SHeiko Carstens }; 63e76e82d7SHeiko Carstens 64e76e82d7SHeiko Carstens static struct addr_marker address_markers[] = { 65*7e12284cSHeiko Carstens [KVA_NR] = {0, 0, "Kernel Virtual Address Space"}, 66*7e12284cSHeiko Carstens [LOWCORE_START_NR] = {1, 0, "Lowcore Start"}, 67*7e12284cSHeiko Carstens [LOWCORE_END_NR] = {0, 0, "Lowcore End"}, 68*7e12284cSHeiko Carstens [IDENTITY_START_NR] = {1, 0, "Identity Mapping Start"}, 69*7e12284cSHeiko Carstens [IDENTITY_END_NR] = {0, 0, "Identity Mapping End"}, 70*7e12284cSHeiko Carstens [AMODE31_START_NR] = {1, 0, "Amode31 Area Start"}, 71*7e12284cSHeiko Carstens [AMODE31_END_NR] = {0, 0, "Amode31 Area End"}, 72*7e12284cSHeiko Carstens [KERNEL_START_NR] = {1, (unsigned long)_stext, "Kernel Image Start"}, 73*7e12284cSHeiko Carstens [KERNEL_END_NR] = {0, (unsigned long)_end, "Kernel Image End"}, 74d6de72cfSSven Schnelle #ifdef CONFIG_KFENCE 75*7e12284cSHeiko Carstens [KFENCE_START_NR] = {1, 0, "KFence Pool Start"}, 76*7e12284cSHeiko Carstens [KFENCE_END_NR] = {0, 0, "KFence Pool End"}, 77d6de72cfSSven Schnelle #endif 78*7e12284cSHeiko Carstens [VMEMMAP_NR] = {1, 0, "vmemmap Area Start"}, 79*7e12284cSHeiko Carstens [VMEMMAP_END_NR] = {0, 0, "vmemmap Area End"}, 80*7e12284cSHeiko Carstens [VMALLOC_NR] = {1, 0, "vmalloc Area Start"}, 81*7e12284cSHeiko Carstens [VMALLOC_END_NR] = {0, 0, "vmalloc Area End"}, 8219af2887SIlya Leoshkevich #ifdef CONFIG_KMSAN 83*7e12284cSHeiko Carstens [KMSAN_VMALLOC_SHADOW_START_NR] = {1, 0, "Kmsan vmalloc Shadow Start"}, 84*7e12284cSHeiko Carstens [KMSAN_VMALLOC_SHADOW_END_NR] = {0, 0, "Kmsan vmalloc Shadow End"}, 85*7e12284cSHeiko Carstens [KMSAN_VMALLOC_ORIGIN_START_NR] = {1, 0, "Kmsan vmalloc Origins Start"}, 86*7e12284cSHeiko Carstens [KMSAN_VMALLOC_ORIGIN_END_NR] = {0, 0, "Kmsan vmalloc Origins End"}, 87*7e12284cSHeiko Carstens [KMSAN_MODULES_SHADOW_START_NR] = {1, 0, "Kmsan Modules Shadow Start"}, 88*7e12284cSHeiko Carstens [KMSAN_MODULES_SHADOW_END_NR] = {0, 0, "Kmsan Modules Shadow End"}, 89*7e12284cSHeiko Carstens [KMSAN_MODULES_ORIGIN_START_NR] = {1, 0, "Kmsan Modules Origins Start"}, 90*7e12284cSHeiko Carstens [KMSAN_MODULES_ORIGIN_END_NR] = {0, 0, "Kmsan Modules Origins End"}, 9119af2887SIlya Leoshkevich #endif 92*7e12284cSHeiko Carstens [MODULES_NR] = {1, 0, "Modules Area Start"}, 93*7e12284cSHeiko Carstens [MODULES_END_NR] = {0, 0, "Modules Area End"}, 94*7e12284cSHeiko Carstens [ABS_LOWCORE_NR] = {1, 0, "Lowcore Area Start"}, 95*7e12284cSHeiko Carstens [ABS_LOWCORE_END_NR] = {0, 0, "Lowcore Area End"}, 96*7e12284cSHeiko Carstens [MEMCPY_REAL_NR] = {1, 0, "Real Memory Copy Area Start"}, 97*7e12284cSHeiko Carstens [MEMCPY_REAL_END_NR] = {0, 0, "Real Memory Copy Area End"}, 9805178996SVasily Gorbik #ifdef CONFIG_KASAN 99*7e12284cSHeiko Carstens [KASAN_SHADOW_START_NR] = {1, KASAN_SHADOW_START, "Kasan Shadow Start"}, 100*7e12284cSHeiko Carstens [KASAN_SHADOW_END_NR] = {0, KASAN_SHADOW_END, "Kasan Shadow End"}, 10105178996SVasily Gorbik #endif 102*7e12284cSHeiko Carstens {1, -1UL, NULL} 103e76e82d7SHeiko Carstens }; 104e76e82d7SHeiko Carstens 105e76e82d7SHeiko Carstens struct pg_state { 1069d719d39SHeiko Carstens struct ptdump_state ptdump; 1079d719d39SHeiko Carstens struct seq_file *seq; 108e76e82d7SHeiko Carstens int level; 109e76e82d7SHeiko Carstens unsigned int current_prot; 11008c8e685SHeiko Carstens bool check_wx; 11108c8e685SHeiko Carstens unsigned long wx_pages; 112e76e82d7SHeiko Carstens unsigned long start_address; 113e76e82d7SHeiko Carstens const struct addr_marker *marker; 114e76e82d7SHeiko Carstens }; 115e76e82d7SHeiko Carstens 1166bf9a639SHeiko Carstens #define pt_dump_seq_printf(m, fmt, args...) \ 1176bf9a639SHeiko Carstens ({ \ 1186bf9a639SHeiko Carstens struct seq_file *__m = (m); \ 1196bf9a639SHeiko Carstens \ 1206bf9a639SHeiko Carstens if (__m) \ 1216bf9a639SHeiko Carstens seq_printf(__m, fmt, ##args); \ 1226bf9a639SHeiko Carstens }) 1236bf9a639SHeiko Carstens 1246bf9a639SHeiko Carstens #define pt_dump_seq_puts(m, fmt) \ 1256bf9a639SHeiko Carstens ({ \ 1266bf9a639SHeiko Carstens struct seq_file *__m = (m); \ 1276bf9a639SHeiko Carstens \ 1286bf9a639SHeiko Carstens if (__m) \ 1296bf9a639SHeiko Carstens seq_printf(__m, fmt); \ 1306bf9a639SHeiko Carstens }) 1316bf9a639SHeiko Carstens 132e76e82d7SHeiko Carstens static void print_prot(struct seq_file *m, unsigned int pr, int level) 133e76e82d7SHeiko Carstens { 134e76e82d7SHeiko Carstens static const char * const level_name[] = 135e76e82d7SHeiko Carstens { "ASCE", "PGD", "PUD", "PMD", "PTE" }; 136e76e82d7SHeiko Carstens 1376bf9a639SHeiko Carstens pt_dump_seq_printf(m, "%s ", level_name[level]); 1381819ed1fSHeiko Carstens if (pr & _PAGE_INVALID) { 1396bf9a639SHeiko Carstens pt_dump_seq_printf(m, "I\n"); 1401819ed1fSHeiko Carstens return; 1411819ed1fSHeiko Carstens } 1426bf9a639SHeiko Carstens pt_dump_seq_puts(m, (pr & _PAGE_PROTECT) ? "RO " : "RW "); 1436bf9a639SHeiko Carstens pt_dump_seq_puts(m, (pr & _PAGE_NOEXEC) ? "NX\n" : "X\n"); 144e76e82d7SHeiko Carstens } 145e76e82d7SHeiko Carstens 14608c8e685SHeiko Carstens static void note_prot_wx(struct pg_state *st, unsigned long addr) 14708c8e685SHeiko Carstens { 14808c8e685SHeiko Carstens if (!st->check_wx) 14908c8e685SHeiko Carstens return; 15008c8e685SHeiko Carstens if (st->current_prot & _PAGE_INVALID) 15108c8e685SHeiko Carstens return; 15208c8e685SHeiko Carstens if (st->current_prot & _PAGE_PROTECT) 15308c8e685SHeiko Carstens return; 15408c8e685SHeiko Carstens if (st->current_prot & _PAGE_NOEXEC) 15508c8e685SHeiko Carstens return; 1563b051e89SSven Schnelle /* 1573b051e89SSven Schnelle * The first lowcore page is W+X if spectre mitigations are using 1583b051e89SSven Schnelle * trampolines or the BEAR enhancements facility is not installed, 1593b051e89SSven Schnelle * in which case we have two lpswe instructions in lowcore that need 1603b051e89SSven Schnelle * to be executable. 1613b051e89SSven Schnelle */ 1623b051e89SSven Schnelle if (addr == PAGE_SIZE && (nospec_uses_trampoline() || !static_key_enabled(&cpu_has_bear))) 16308c8e685SHeiko Carstens return; 164592e15f6SChristophe Leroy WARN_ONCE(IS_ENABLED(CONFIG_DEBUG_WX), 165592e15f6SChristophe Leroy "s390/mm: Found insecure W+X mapping at address %pS\n", 16608c8e685SHeiko Carstens (void *)st->start_address); 16708c8e685SHeiko Carstens st->wx_pages += (addr - st->start_address) / PAGE_SIZE; 16808c8e685SHeiko Carstens } 16908c8e685SHeiko Carstens 1707e4d4cfeSHeiko Carstens static void note_page_update_state(struct pg_state *st, unsigned long addr, unsigned int prot, int level) 1717e4d4cfeSHeiko Carstens { 1727e4d4cfeSHeiko Carstens struct seq_file *m = st->seq; 1737e4d4cfeSHeiko Carstens 1747e4d4cfeSHeiko Carstens while (addr >= st->marker[1].start_address) { 1757e4d4cfeSHeiko Carstens st->marker++; 1767e4d4cfeSHeiko Carstens pt_dump_seq_printf(m, "---[ %s ]---\n", st->marker->name); 1777e4d4cfeSHeiko Carstens } 1787e4d4cfeSHeiko Carstens st->start_address = addr; 1797e4d4cfeSHeiko Carstens st->current_prot = prot; 1807e4d4cfeSHeiko Carstens st->level = level; 1817e4d4cfeSHeiko Carstens } 1827e4d4cfeSHeiko Carstens 1839d719d39SHeiko Carstens static void note_page(struct ptdump_state *pt_st, unsigned long addr, int level, u64 val) 184e76e82d7SHeiko Carstens { 185e76e82d7SHeiko Carstens int width = sizeof(unsigned long) * 2; 1869d719d39SHeiko Carstens static const char units[] = "KMGTPE"; 187e76e82d7SHeiko Carstens const char *unit = units; 188e76e82d7SHeiko Carstens unsigned long delta; 1899d719d39SHeiko Carstens struct pg_state *st; 1909d719d39SHeiko Carstens struct seq_file *m; 1919d719d39SHeiko Carstens unsigned int prot; 192e76e82d7SHeiko Carstens 1939d719d39SHeiko Carstens st = container_of(pt_st, struct pg_state, ptdump); 1949d719d39SHeiko Carstens m = st->seq; 1959d719d39SHeiko Carstens prot = val & (_PAGE_PROTECT | _PAGE_NOEXEC); 1969d719d39SHeiko Carstens if (level == 4 && (val & _PAGE_INVALID)) 1979d719d39SHeiko Carstens prot = _PAGE_INVALID; 1989d719d39SHeiko Carstens /* For pmd_none() & friends val gets passed as zero. */ 1999d719d39SHeiko Carstens if (level != 4 && !val) 2009d719d39SHeiko Carstens prot = _PAGE_INVALID; 2019d719d39SHeiko Carstens /* Final flush from generic code. */ 2029d719d39SHeiko Carstens if (level == -1) 2039d719d39SHeiko Carstens addr = max_addr; 2049d719d39SHeiko Carstens if (st->level == -1) { 2056bf9a639SHeiko Carstens pt_dump_seq_printf(m, "---[ %s ]---\n", st->marker->name); 2067e4d4cfeSHeiko Carstens note_page_update_state(st, addr, prot, level); 2079d719d39SHeiko Carstens } else if (prot != st->current_prot || level != st->level || 2089d719d39SHeiko Carstens addr >= st->marker[1].start_address) { 20908c8e685SHeiko Carstens note_prot_wx(st, addr); 2106bf9a639SHeiko Carstens pt_dump_seq_printf(m, "0x%0*lx-0x%0*lx ", 211e76e82d7SHeiko Carstens width, st->start_address, 2129d719d39SHeiko Carstens width, addr); 2139d719d39SHeiko Carstens delta = (addr - st->start_address) >> 10; 214e76e82d7SHeiko Carstens while (!(delta & 0x3ff) && unit[1]) { 215e76e82d7SHeiko Carstens delta >>= 10; 216e76e82d7SHeiko Carstens unit++; 217e76e82d7SHeiko Carstens } 2186bf9a639SHeiko Carstens pt_dump_seq_printf(m, "%9lu%c ", delta, *unit); 219e76e82d7SHeiko Carstens print_prot(m, st->current_prot, st->level); 2207e4d4cfeSHeiko Carstens note_page_update_state(st, addr, prot, level); 221e76e82d7SHeiko Carstens } 222e76e82d7SHeiko Carstens } 223e76e82d7SHeiko Carstens 2246cdc82dbSChristophe Leroy bool ptdump_check_wx(void) 22508c8e685SHeiko Carstens { 22608c8e685SHeiko Carstens struct pg_state st = { 22708c8e685SHeiko Carstens .ptdump = { 22808c8e685SHeiko Carstens .note_page = note_page, 22908c8e685SHeiko Carstens .range = (struct ptdump_range[]) { 23008c8e685SHeiko Carstens {.start = 0, .end = max_addr}, 23108c8e685SHeiko Carstens {.start = 0, .end = 0}, 23208c8e685SHeiko Carstens } 23308c8e685SHeiko Carstens }, 23408c8e685SHeiko Carstens .seq = NULL, 23508c8e685SHeiko Carstens .level = -1, 23608c8e685SHeiko Carstens .current_prot = 0, 23708c8e685SHeiko Carstens .check_wx = true, 23808c8e685SHeiko Carstens .wx_pages = 0, 23908c8e685SHeiko Carstens .start_address = 0, 24008c8e685SHeiko Carstens .marker = (struct addr_marker[]) { 24108c8e685SHeiko Carstens { .start_address = 0, .name = NULL}, 24208c8e685SHeiko Carstens { .start_address = -1, .name = NULL}, 24308c8e685SHeiko Carstens }, 24408c8e685SHeiko Carstens }; 24508c8e685SHeiko Carstens 24608c8e685SHeiko Carstens if (!MACHINE_HAS_NX) 2476cdc82dbSChristophe Leroy return true; 24808c8e685SHeiko Carstens ptdump_walk_pgd(&st.ptdump, &init_mm, NULL); 2496cdc82dbSChristophe Leroy if (st.wx_pages) { 25008c8e685SHeiko Carstens pr_warn("Checked W+X mappings: FAILED, %lu W+X pages found\n", st.wx_pages); 2516cdc82dbSChristophe Leroy 2526cdc82dbSChristophe Leroy return false; 2536cdc82dbSChristophe Leroy } else { 2543b051e89SSven Schnelle pr_info("Checked W+X mappings: passed, no %sW+X pages found\n", 2553b051e89SSven Schnelle (nospec_uses_trampoline() || !static_key_enabled(&cpu_has_bear)) ? 2563b051e89SSven Schnelle "unexpected " : ""); 2576cdc82dbSChristophe Leroy 2586cdc82dbSChristophe Leroy return true; 2596cdc82dbSChristophe Leroy } 26008c8e685SHeiko Carstens } 26108c8e685SHeiko Carstens 26208c8e685SHeiko Carstens #ifdef CONFIG_PTDUMP_DEBUGFS 263e76e82d7SHeiko Carstens static int ptdump_show(struct seq_file *m, void *v) 264e76e82d7SHeiko Carstens { 2659d719d39SHeiko Carstens struct pg_state st = { 2669d719d39SHeiko Carstens .ptdump = { 2679d719d39SHeiko Carstens .note_page = note_page, 2689d719d39SHeiko Carstens .range = (struct ptdump_range[]) { 2699d719d39SHeiko Carstens {.start = 0, .end = max_addr}, 2709d719d39SHeiko Carstens {.start = 0, .end = 0}, 2719d719d39SHeiko Carstens } 2729d719d39SHeiko Carstens }, 2739d719d39SHeiko Carstens .seq = m, 2749d719d39SHeiko Carstens .level = -1, 2759d719d39SHeiko Carstens .current_prot = 0, 27608c8e685SHeiko Carstens .check_wx = false, 27708c8e685SHeiko Carstens .wx_pages = 0, 2789d719d39SHeiko Carstens .start_address = 0, 2799d719d39SHeiko Carstens .marker = address_markers, 2809d719d39SHeiko Carstens }; 2819d719d39SHeiko Carstens 28236c2733cSHeiko Carstens get_online_mems(); 283da1694adSHeiko Carstens mutex_lock(&cpa_mutex); 2849d719d39SHeiko Carstens ptdump_walk_pgd(&st.ptdump, &init_mm, NULL); 285da1694adSHeiko Carstens mutex_unlock(&cpa_mutex); 28636c2733cSHeiko Carstens put_online_mems(); 287e76e82d7SHeiko Carstens return 0; 288e76e82d7SHeiko Carstens } 2899d719d39SHeiko Carstens DEFINE_SHOW_ATTRIBUTE(ptdump); 29008c8e685SHeiko Carstens #endif /* CONFIG_PTDUMP_DEBUGFS */ 291e76e82d7SHeiko Carstens 292*7e12284cSHeiko Carstens static int ptdump_cmp(const void *a, const void *b) 293ee4b2ce6SVasily Gorbik { 294*7e12284cSHeiko Carstens const struct addr_marker *ama = a; 295*7e12284cSHeiko Carstens const struct addr_marker *amb = b; 296ee4b2ce6SVasily Gorbik 297*7e12284cSHeiko Carstens if (ama->start_address > amb->start_address) 298*7e12284cSHeiko Carstens return 1; 299*7e12284cSHeiko Carstens if (ama->start_address < amb->start_address) 300*7e12284cSHeiko Carstens return -1; 301*7e12284cSHeiko Carstens /* 302*7e12284cSHeiko Carstens * If the start addresses of two markers are identical consider the 303*7e12284cSHeiko Carstens * marker which defines the start of an area higher than the one which 304*7e12284cSHeiko Carstens * defines the end of an area. This keeps pairs of markers sorted. 305*7e12284cSHeiko Carstens */ 306*7e12284cSHeiko Carstens if (ama->is_start) 307*7e12284cSHeiko Carstens return 1; 308*7e12284cSHeiko Carstens if (amb->is_start) 309*7e12284cSHeiko Carstens return -1; 310*7e12284cSHeiko Carstens return 0; 311ee4b2ce6SVasily Gorbik } 312ee4b2ce6SVasily Gorbik 313e76e82d7SHeiko Carstens static int pt_dump_init(void) 314e76e82d7SHeiko Carstens { 315d6de72cfSSven Schnelle #ifdef CONFIG_KFENCE 316d6de72cfSSven Schnelle unsigned long kfence_start = (unsigned long)__kfence_pool; 317d6de72cfSSven Schnelle #endif 3187e4d4cfeSHeiko Carstens unsigned long lowcore = (unsigned long)get_lowcore(); 3197e4d4cfeSHeiko Carstens 320e76e82d7SHeiko Carstens /* 321e76e82d7SHeiko Carstens * Figure out the maximum virtual address being accessible with the 322e76e82d7SHeiko Carstens * kernel ASCE. We need this to keep the page table walker functions 323e76e82d7SHeiko Carstens * from accessing non-existent entries. 324e76e82d7SHeiko Carstens */ 325208da1d5SSven Schnelle max_addr = (get_lowcore()->kernel_asce.val & _REGION_ENTRY_TYPE_MASK) >> 2; 326e76e82d7SHeiko Carstens max_addr = 1UL << (max_addr * 11 + 31); 3277e4d4cfeSHeiko Carstens address_markers[LOWCORE_START_NR].start_address = lowcore; 3287e4d4cfeSHeiko Carstens address_markers[LOWCORE_END_NR].start_address = lowcore + sizeof(struct lowcore); 32937395344SHeiko Carstens address_markers[IDENTITY_START_NR].start_address = __identity_base; 33037395344SHeiko Carstens address_markers[IDENTITY_END_NR].start_address = __identity_base + ident_map_size; 3313eeb0778SHeiko Carstens address_markers[AMODE31_START_NR].start_address = (unsigned long)__samode31; 3323eeb0778SHeiko Carstens address_markers[AMODE31_END_NR].start_address = (unsigned long)__eamode31; 333c972cc60SHeiko Carstens address_markers[MODULES_NR].start_address = MODULES_VADDR; 334e670e64aSVasily Gorbik address_markers[MODULES_END_NR].start_address = MODULES_END; 33550787755SAlexander Gordeev address_markers[ABS_LOWCORE_NR].start_address = __abs_lowcore; 33650787755SAlexander Gordeev address_markers[ABS_LOWCORE_END_NR].start_address = __abs_lowcore + ABS_LOWCORE_MAP_SIZE; 337c0ceb944SAlexander Gordeev address_markers[MEMCPY_REAL_NR].start_address = __memcpy_real_area; 338a984f27eSAlexander Gordeev address_markers[MEMCPY_REAL_END_NR].start_address = __memcpy_real_area + MEMCPY_REAL_SIZE; 339e76e82d7SHeiko Carstens address_markers[VMEMMAP_NR].start_address = (unsigned long) vmemmap; 340e670e64aSVasily Gorbik address_markers[VMEMMAP_END_NR].start_address = (unsigned long)vmemmap + vmemmap_size; 341e76e82d7SHeiko Carstens address_markers[VMALLOC_NR].start_address = VMALLOC_START; 342e670e64aSVasily Gorbik address_markers[VMALLOC_END_NR].start_address = VMALLOC_END; 343d6de72cfSSven Schnelle #ifdef CONFIG_KFENCE 344d6de72cfSSven Schnelle address_markers[KFENCE_START_NR].start_address = kfence_start; 345d6de72cfSSven Schnelle address_markers[KFENCE_END_NR].start_address = kfence_start + KFENCE_POOL_SIZE; 346d6de72cfSSven Schnelle #endif 34719af2887SIlya Leoshkevich #ifdef CONFIG_KMSAN 34819af2887SIlya Leoshkevich address_markers[KMSAN_VMALLOC_SHADOW_START_NR].start_address = KMSAN_VMALLOC_SHADOW_START; 34919af2887SIlya Leoshkevich address_markers[KMSAN_VMALLOC_SHADOW_END_NR].start_address = KMSAN_VMALLOC_SHADOW_END; 35019af2887SIlya Leoshkevich address_markers[KMSAN_VMALLOC_ORIGIN_START_NR].start_address = KMSAN_VMALLOC_ORIGIN_START; 35119af2887SIlya Leoshkevich address_markers[KMSAN_VMALLOC_ORIGIN_END_NR].start_address = KMSAN_VMALLOC_ORIGIN_END; 35219af2887SIlya Leoshkevich address_markers[KMSAN_MODULES_SHADOW_START_NR].start_address = KMSAN_MODULES_SHADOW_START; 35319af2887SIlya Leoshkevich address_markers[KMSAN_MODULES_SHADOW_END_NR].start_address = KMSAN_MODULES_SHADOW_END; 35419af2887SIlya Leoshkevich address_markers[KMSAN_MODULES_ORIGIN_START_NR].start_address = KMSAN_MODULES_ORIGIN_START; 35519af2887SIlya Leoshkevich address_markers[KMSAN_MODULES_ORIGIN_END_NR].start_address = KMSAN_MODULES_ORIGIN_END; 35619af2887SIlya Leoshkevich #endif 357*7e12284cSHeiko Carstens sort(address_markers, ARRAY_SIZE(address_markers) - 1, 358*7e12284cSHeiko Carstens sizeof(address_markers[0]), ptdump_cmp, NULL); 35948111b48SHeiko Carstens #ifdef CONFIG_PTDUMP_DEBUGFS 360e76e82d7SHeiko Carstens debugfs_create_file("kernel_page_tables", 0400, NULL, NULL, &ptdump_fops); 36148111b48SHeiko Carstens #endif /* CONFIG_PTDUMP_DEBUGFS */ 362e76e82d7SHeiko Carstens return 0; 363e76e82d7SHeiko Carstens } 364e76e82d7SHeiko Carstens device_initcall(pt_dump_init); 365