162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2014, The Linux Foundation. All rights reserved. 462306a36Sopenharmony_ci * Debug helper to dump the current kernel pagetables of the system 562306a36Sopenharmony_ci * so that we can see what the various memory ranges are set to. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Derived from x86 and arm implementation: 862306a36Sopenharmony_ci * (C) Copyright 2008 Intel Corporation 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Author: Arjan van de Ven <arjan@linux.intel.com> 1162306a36Sopenharmony_ci */ 1262306a36Sopenharmony_ci#include <linux/debugfs.h> 1362306a36Sopenharmony_ci#include <linux/errno.h> 1462306a36Sopenharmony_ci#include <linux/fs.h> 1562306a36Sopenharmony_ci#include <linux/io.h> 1662306a36Sopenharmony_ci#include <linux/init.h> 1762306a36Sopenharmony_ci#include <linux/mm.h> 1862306a36Sopenharmony_ci#include <linux/ptdump.h> 1962306a36Sopenharmony_ci#include <linux/sched.h> 2062306a36Sopenharmony_ci#include <linux/seq_file.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include <asm/fixmap.h> 2362306a36Sopenharmony_ci#include <asm/kasan.h> 2462306a36Sopenharmony_ci#include <asm/memory.h> 2562306a36Sopenharmony_ci#include <asm/pgtable-hwdef.h> 2662306a36Sopenharmony_ci#include <asm/ptdump.h> 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cienum address_markers_idx { 3062306a36Sopenharmony_ci PAGE_OFFSET_NR = 0, 3162306a36Sopenharmony_ci PAGE_END_NR, 3262306a36Sopenharmony_ci#if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS) 3362306a36Sopenharmony_ci KASAN_START_NR, 3462306a36Sopenharmony_ci#endif 3562306a36Sopenharmony_ci}; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistatic struct addr_marker address_markers[] = { 3862306a36Sopenharmony_ci { PAGE_OFFSET, "Linear Mapping start" }, 3962306a36Sopenharmony_ci { 0 /* PAGE_END */, "Linear Mapping end" }, 4062306a36Sopenharmony_ci#if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS) 4162306a36Sopenharmony_ci { 0 /* KASAN_SHADOW_START */, "Kasan shadow start" }, 4262306a36Sopenharmony_ci { KASAN_SHADOW_END, "Kasan shadow end" }, 4362306a36Sopenharmony_ci#endif 4462306a36Sopenharmony_ci { MODULES_VADDR, "Modules start" }, 4562306a36Sopenharmony_ci { MODULES_END, "Modules end" }, 4662306a36Sopenharmony_ci { VMALLOC_START, "vmalloc() area" }, 4762306a36Sopenharmony_ci { VMALLOC_END, "vmalloc() end" }, 4862306a36Sopenharmony_ci { FIXADDR_TOT_START, "Fixmap start" }, 4962306a36Sopenharmony_ci { FIXADDR_TOP, "Fixmap end" }, 5062306a36Sopenharmony_ci { PCI_IO_START, "PCI I/O start" }, 5162306a36Sopenharmony_ci { PCI_IO_END, "PCI I/O end" }, 5262306a36Sopenharmony_ci { VMEMMAP_START, "vmemmap start" }, 5362306a36Sopenharmony_ci { VMEMMAP_START + VMEMMAP_SIZE, "vmemmap end" }, 5462306a36Sopenharmony_ci { -1, NULL }, 5562306a36Sopenharmony_ci}; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci#define pt_dump_seq_printf(m, fmt, args...) \ 5862306a36Sopenharmony_ci({ \ 5962306a36Sopenharmony_ci if (m) \ 6062306a36Sopenharmony_ci seq_printf(m, fmt, ##args); \ 6162306a36Sopenharmony_ci}) 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci#define pt_dump_seq_puts(m, fmt) \ 6462306a36Sopenharmony_ci({ \ 6562306a36Sopenharmony_ci if (m) \ 6662306a36Sopenharmony_ci seq_printf(m, fmt); \ 6762306a36Sopenharmony_ci}) 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci/* 7062306a36Sopenharmony_ci * The page dumper groups page table entries of the same type into a single 7162306a36Sopenharmony_ci * description. It uses pg_state to track the range information while 7262306a36Sopenharmony_ci * iterating over the pte entries. When the continuity is broken it then 7362306a36Sopenharmony_ci * dumps out a description of the range. 7462306a36Sopenharmony_ci */ 7562306a36Sopenharmony_cistruct pg_state { 7662306a36Sopenharmony_ci struct ptdump_state ptdump; 7762306a36Sopenharmony_ci struct seq_file *seq; 7862306a36Sopenharmony_ci const struct addr_marker *marker; 7962306a36Sopenharmony_ci unsigned long start_address; 8062306a36Sopenharmony_ci int level; 8162306a36Sopenharmony_ci u64 current_prot; 8262306a36Sopenharmony_ci bool check_wx; 8362306a36Sopenharmony_ci unsigned long wx_pages; 8462306a36Sopenharmony_ci unsigned long uxn_pages; 8562306a36Sopenharmony_ci}; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistruct prot_bits { 8862306a36Sopenharmony_ci u64 mask; 8962306a36Sopenharmony_ci u64 val; 9062306a36Sopenharmony_ci const char *set; 9162306a36Sopenharmony_ci const char *clear; 9262306a36Sopenharmony_ci}; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_cistatic const struct prot_bits pte_bits[] = { 9562306a36Sopenharmony_ci { 9662306a36Sopenharmony_ci .mask = PTE_VALID, 9762306a36Sopenharmony_ci .val = PTE_VALID, 9862306a36Sopenharmony_ci .set = " ", 9962306a36Sopenharmony_ci .clear = "F", 10062306a36Sopenharmony_ci }, { 10162306a36Sopenharmony_ci .mask = PTE_USER, 10262306a36Sopenharmony_ci .val = PTE_USER, 10362306a36Sopenharmony_ci .set = "USR", 10462306a36Sopenharmony_ci .clear = " ", 10562306a36Sopenharmony_ci }, { 10662306a36Sopenharmony_ci .mask = PTE_RDONLY, 10762306a36Sopenharmony_ci .val = PTE_RDONLY, 10862306a36Sopenharmony_ci .set = "ro", 10962306a36Sopenharmony_ci .clear = "RW", 11062306a36Sopenharmony_ci }, { 11162306a36Sopenharmony_ci .mask = PTE_PXN, 11262306a36Sopenharmony_ci .val = PTE_PXN, 11362306a36Sopenharmony_ci .set = "NX", 11462306a36Sopenharmony_ci .clear = "x ", 11562306a36Sopenharmony_ci }, { 11662306a36Sopenharmony_ci .mask = PTE_SHARED, 11762306a36Sopenharmony_ci .val = PTE_SHARED, 11862306a36Sopenharmony_ci .set = "SHD", 11962306a36Sopenharmony_ci .clear = " ", 12062306a36Sopenharmony_ci }, { 12162306a36Sopenharmony_ci .mask = PTE_AF, 12262306a36Sopenharmony_ci .val = PTE_AF, 12362306a36Sopenharmony_ci .set = "AF", 12462306a36Sopenharmony_ci .clear = " ", 12562306a36Sopenharmony_ci }, { 12662306a36Sopenharmony_ci .mask = PTE_NG, 12762306a36Sopenharmony_ci .val = PTE_NG, 12862306a36Sopenharmony_ci .set = "NG", 12962306a36Sopenharmony_ci .clear = " ", 13062306a36Sopenharmony_ci }, { 13162306a36Sopenharmony_ci .mask = PTE_CONT, 13262306a36Sopenharmony_ci .val = PTE_CONT, 13362306a36Sopenharmony_ci .set = "CON", 13462306a36Sopenharmony_ci .clear = " ", 13562306a36Sopenharmony_ci }, { 13662306a36Sopenharmony_ci .mask = PTE_TABLE_BIT, 13762306a36Sopenharmony_ci .val = PTE_TABLE_BIT, 13862306a36Sopenharmony_ci .set = " ", 13962306a36Sopenharmony_ci .clear = "BLK", 14062306a36Sopenharmony_ci }, { 14162306a36Sopenharmony_ci .mask = PTE_UXN, 14262306a36Sopenharmony_ci .val = PTE_UXN, 14362306a36Sopenharmony_ci .set = "UXN", 14462306a36Sopenharmony_ci .clear = " ", 14562306a36Sopenharmony_ci }, { 14662306a36Sopenharmony_ci .mask = PTE_GP, 14762306a36Sopenharmony_ci .val = PTE_GP, 14862306a36Sopenharmony_ci .set = "GP", 14962306a36Sopenharmony_ci .clear = " ", 15062306a36Sopenharmony_ci }, { 15162306a36Sopenharmony_ci .mask = PTE_ATTRINDX_MASK, 15262306a36Sopenharmony_ci .val = PTE_ATTRINDX(MT_DEVICE_nGnRnE), 15362306a36Sopenharmony_ci .set = "DEVICE/nGnRnE", 15462306a36Sopenharmony_ci }, { 15562306a36Sopenharmony_ci .mask = PTE_ATTRINDX_MASK, 15662306a36Sopenharmony_ci .val = PTE_ATTRINDX(MT_DEVICE_nGnRE), 15762306a36Sopenharmony_ci .set = "DEVICE/nGnRE", 15862306a36Sopenharmony_ci }, { 15962306a36Sopenharmony_ci .mask = PTE_ATTRINDX_MASK, 16062306a36Sopenharmony_ci .val = PTE_ATTRINDX(MT_NORMAL_NC), 16162306a36Sopenharmony_ci .set = "MEM/NORMAL-NC", 16262306a36Sopenharmony_ci }, { 16362306a36Sopenharmony_ci .mask = PTE_ATTRINDX_MASK, 16462306a36Sopenharmony_ci .val = PTE_ATTRINDX(MT_NORMAL), 16562306a36Sopenharmony_ci .set = "MEM/NORMAL", 16662306a36Sopenharmony_ci }, { 16762306a36Sopenharmony_ci .mask = PTE_ATTRINDX_MASK, 16862306a36Sopenharmony_ci .val = PTE_ATTRINDX(MT_NORMAL_TAGGED), 16962306a36Sopenharmony_ci .set = "MEM/NORMAL-TAGGED", 17062306a36Sopenharmony_ci } 17162306a36Sopenharmony_ci}; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_cistruct pg_level { 17462306a36Sopenharmony_ci const struct prot_bits *bits; 17562306a36Sopenharmony_ci const char *name; 17662306a36Sopenharmony_ci size_t num; 17762306a36Sopenharmony_ci u64 mask; 17862306a36Sopenharmony_ci}; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_cistatic struct pg_level pg_level[] = { 18162306a36Sopenharmony_ci { /* pgd */ 18262306a36Sopenharmony_ci .name = "PGD", 18362306a36Sopenharmony_ci .bits = pte_bits, 18462306a36Sopenharmony_ci .num = ARRAY_SIZE(pte_bits), 18562306a36Sopenharmony_ci }, { /* p4d */ 18662306a36Sopenharmony_ci .name = "P4D", 18762306a36Sopenharmony_ci .bits = pte_bits, 18862306a36Sopenharmony_ci .num = ARRAY_SIZE(pte_bits), 18962306a36Sopenharmony_ci }, { /* pud */ 19062306a36Sopenharmony_ci .name = (CONFIG_PGTABLE_LEVELS > 3) ? "PUD" : "PGD", 19162306a36Sopenharmony_ci .bits = pte_bits, 19262306a36Sopenharmony_ci .num = ARRAY_SIZE(pte_bits), 19362306a36Sopenharmony_ci }, { /* pmd */ 19462306a36Sopenharmony_ci .name = (CONFIG_PGTABLE_LEVELS > 2) ? "PMD" : "PGD", 19562306a36Sopenharmony_ci .bits = pte_bits, 19662306a36Sopenharmony_ci .num = ARRAY_SIZE(pte_bits), 19762306a36Sopenharmony_ci }, { /* pte */ 19862306a36Sopenharmony_ci .name = "PTE", 19962306a36Sopenharmony_ci .bits = pte_bits, 20062306a36Sopenharmony_ci .num = ARRAY_SIZE(pte_bits), 20162306a36Sopenharmony_ci }, 20262306a36Sopenharmony_ci}; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_cistatic void dump_prot(struct pg_state *st, const struct prot_bits *bits, 20562306a36Sopenharmony_ci size_t num) 20662306a36Sopenharmony_ci{ 20762306a36Sopenharmony_ci unsigned i; 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci for (i = 0; i < num; i++, bits++) { 21062306a36Sopenharmony_ci const char *s; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci if ((st->current_prot & bits->mask) == bits->val) 21362306a36Sopenharmony_ci s = bits->set; 21462306a36Sopenharmony_ci else 21562306a36Sopenharmony_ci s = bits->clear; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci if (s) 21862306a36Sopenharmony_ci pt_dump_seq_printf(st->seq, " %s", s); 21962306a36Sopenharmony_ci } 22062306a36Sopenharmony_ci} 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_cistatic void note_prot_uxn(struct pg_state *st, unsigned long addr) 22362306a36Sopenharmony_ci{ 22462306a36Sopenharmony_ci if (!st->check_wx) 22562306a36Sopenharmony_ci return; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci if ((st->current_prot & PTE_UXN) == PTE_UXN) 22862306a36Sopenharmony_ci return; 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci WARN_ONCE(1, "arm64/mm: Found non-UXN mapping at address %p/%pS\n", 23162306a36Sopenharmony_ci (void *)st->start_address, (void *)st->start_address); 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci st->uxn_pages += (addr - st->start_address) / PAGE_SIZE; 23462306a36Sopenharmony_ci} 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_cistatic void note_prot_wx(struct pg_state *st, unsigned long addr) 23762306a36Sopenharmony_ci{ 23862306a36Sopenharmony_ci if (!st->check_wx) 23962306a36Sopenharmony_ci return; 24062306a36Sopenharmony_ci if ((st->current_prot & PTE_RDONLY) == PTE_RDONLY) 24162306a36Sopenharmony_ci return; 24262306a36Sopenharmony_ci if ((st->current_prot & PTE_PXN) == PTE_PXN) 24362306a36Sopenharmony_ci return; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci WARN_ONCE(1, "arm64/mm: Found insecure W+X mapping at address %p/%pS\n", 24662306a36Sopenharmony_ci (void *)st->start_address, (void *)st->start_address); 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci st->wx_pages += (addr - st->start_address) / PAGE_SIZE; 24962306a36Sopenharmony_ci} 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_cistatic void note_page(struct ptdump_state *pt_st, unsigned long addr, int level, 25262306a36Sopenharmony_ci u64 val) 25362306a36Sopenharmony_ci{ 25462306a36Sopenharmony_ci struct pg_state *st = container_of(pt_st, struct pg_state, ptdump); 25562306a36Sopenharmony_ci static const char units[] = "KMGTPE"; 25662306a36Sopenharmony_ci u64 prot = 0; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci if (level >= 0) 25962306a36Sopenharmony_ci prot = val & pg_level[level].mask; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci if (st->level == -1) { 26262306a36Sopenharmony_ci st->level = level; 26362306a36Sopenharmony_ci st->current_prot = prot; 26462306a36Sopenharmony_ci st->start_address = addr; 26562306a36Sopenharmony_ci pt_dump_seq_printf(st->seq, "---[ %s ]---\n", st->marker->name); 26662306a36Sopenharmony_ci } else if (prot != st->current_prot || level != st->level || 26762306a36Sopenharmony_ci addr >= st->marker[1].start_address) { 26862306a36Sopenharmony_ci const char *unit = units; 26962306a36Sopenharmony_ci unsigned long delta; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci if (st->current_prot) { 27262306a36Sopenharmony_ci note_prot_uxn(st, addr); 27362306a36Sopenharmony_ci note_prot_wx(st, addr); 27462306a36Sopenharmony_ci } 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci pt_dump_seq_printf(st->seq, "0x%016lx-0x%016lx ", 27762306a36Sopenharmony_ci st->start_address, addr); 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci delta = (addr - st->start_address) >> 10; 28062306a36Sopenharmony_ci while (!(delta & 1023) && unit[1]) { 28162306a36Sopenharmony_ci delta >>= 10; 28262306a36Sopenharmony_ci unit++; 28362306a36Sopenharmony_ci } 28462306a36Sopenharmony_ci pt_dump_seq_printf(st->seq, "%9lu%c %s", delta, *unit, 28562306a36Sopenharmony_ci pg_level[st->level].name); 28662306a36Sopenharmony_ci if (st->current_prot && pg_level[st->level].bits) 28762306a36Sopenharmony_ci dump_prot(st, pg_level[st->level].bits, 28862306a36Sopenharmony_ci pg_level[st->level].num); 28962306a36Sopenharmony_ci pt_dump_seq_puts(st->seq, "\n"); 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci if (addr >= st->marker[1].start_address) { 29262306a36Sopenharmony_ci st->marker++; 29362306a36Sopenharmony_ci pt_dump_seq_printf(st->seq, "---[ %s ]---\n", st->marker->name); 29462306a36Sopenharmony_ci } 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci st->start_address = addr; 29762306a36Sopenharmony_ci st->current_prot = prot; 29862306a36Sopenharmony_ci st->level = level; 29962306a36Sopenharmony_ci } 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci if (addr >= st->marker[1].start_address) { 30262306a36Sopenharmony_ci st->marker++; 30362306a36Sopenharmony_ci pt_dump_seq_printf(st->seq, "---[ %s ]---\n", st->marker->name); 30462306a36Sopenharmony_ci } 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci} 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_civoid ptdump_walk(struct seq_file *s, struct ptdump_info *info) 30962306a36Sopenharmony_ci{ 31062306a36Sopenharmony_ci unsigned long end = ~0UL; 31162306a36Sopenharmony_ci struct pg_state st; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci if (info->base_addr < TASK_SIZE_64) 31462306a36Sopenharmony_ci end = TASK_SIZE_64; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci st = (struct pg_state){ 31762306a36Sopenharmony_ci .seq = s, 31862306a36Sopenharmony_ci .marker = info->markers, 31962306a36Sopenharmony_ci .level = -1, 32062306a36Sopenharmony_ci .ptdump = { 32162306a36Sopenharmony_ci .note_page = note_page, 32262306a36Sopenharmony_ci .range = (struct ptdump_range[]){ 32362306a36Sopenharmony_ci {info->base_addr, end}, 32462306a36Sopenharmony_ci {0, 0} 32562306a36Sopenharmony_ci } 32662306a36Sopenharmony_ci } 32762306a36Sopenharmony_ci }; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci ptdump_walk_pgd(&st.ptdump, info->mm, NULL); 33062306a36Sopenharmony_ci} 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_cistatic void __init ptdump_initialize(void) 33362306a36Sopenharmony_ci{ 33462306a36Sopenharmony_ci unsigned i, j; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(pg_level); i++) 33762306a36Sopenharmony_ci if (pg_level[i].bits) 33862306a36Sopenharmony_ci for (j = 0; j < pg_level[i].num; j++) 33962306a36Sopenharmony_ci pg_level[i].mask |= pg_level[i].bits[j].mask; 34062306a36Sopenharmony_ci} 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_cistatic struct ptdump_info kernel_ptdump_info = { 34362306a36Sopenharmony_ci .mm = &init_mm, 34462306a36Sopenharmony_ci .markers = address_markers, 34562306a36Sopenharmony_ci .base_addr = PAGE_OFFSET, 34662306a36Sopenharmony_ci}; 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_civoid ptdump_check_wx(void) 34962306a36Sopenharmony_ci{ 35062306a36Sopenharmony_ci struct pg_state st = { 35162306a36Sopenharmony_ci .seq = NULL, 35262306a36Sopenharmony_ci .marker = (struct addr_marker[]) { 35362306a36Sopenharmony_ci { 0, NULL}, 35462306a36Sopenharmony_ci { -1, NULL}, 35562306a36Sopenharmony_ci }, 35662306a36Sopenharmony_ci .level = -1, 35762306a36Sopenharmony_ci .check_wx = true, 35862306a36Sopenharmony_ci .ptdump = { 35962306a36Sopenharmony_ci .note_page = note_page, 36062306a36Sopenharmony_ci .range = (struct ptdump_range[]) { 36162306a36Sopenharmony_ci {PAGE_OFFSET, ~0UL}, 36262306a36Sopenharmony_ci {0, 0} 36362306a36Sopenharmony_ci } 36462306a36Sopenharmony_ci } 36562306a36Sopenharmony_ci }; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci ptdump_walk_pgd(&st.ptdump, &init_mm, NULL); 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci if (st.wx_pages || st.uxn_pages) 37062306a36Sopenharmony_ci pr_warn("Checked W+X mappings: FAILED, %lu W+X pages found, %lu non-UXN pages found\n", 37162306a36Sopenharmony_ci st.wx_pages, st.uxn_pages); 37262306a36Sopenharmony_ci else 37362306a36Sopenharmony_ci pr_info("Checked W+X mappings: passed, no W+X pages found\n"); 37462306a36Sopenharmony_ci} 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_cistatic int __init ptdump_init(void) 37762306a36Sopenharmony_ci{ 37862306a36Sopenharmony_ci address_markers[PAGE_END_NR].start_address = PAGE_END; 37962306a36Sopenharmony_ci#if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS) 38062306a36Sopenharmony_ci address_markers[KASAN_START_NR].start_address = KASAN_SHADOW_START; 38162306a36Sopenharmony_ci#endif 38262306a36Sopenharmony_ci ptdump_initialize(); 38362306a36Sopenharmony_ci ptdump_debugfs_register(&kernel_ptdump_info, "kernel_page_tables"); 38462306a36Sopenharmony_ci return 0; 38562306a36Sopenharmony_ci} 38662306a36Sopenharmony_cidevice_initcall(ptdump_init); 387