^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Debug helper to dump the current kernel pagetables of the system
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * so that we can see what the various memory ranges are set to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Derived from x86 implementation:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * (C) Copyright 2008 Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Author: Arjan van de Ven <arjan@linux.intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <asm/domain.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/fixmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/memory.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/ptdump.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) static struct addr_marker address_markers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) { MODULES_VADDR, "Modules" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) { PAGE_OFFSET, "Kernel Mapping" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) { 0, "vmalloc() Area" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) { VMALLOC_END, "vmalloc() End" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) { FIXADDR_START, "Fixmap Area" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) { VECTORS_BASE, "Vectors" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) { VECTORS_BASE + PAGE_SIZE * 2, "Vectors End" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) { -1, NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define pt_dump_seq_printf(m, fmt, args...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) if (m) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) seq_printf(m, fmt, ##args); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define pt_dump_seq_puts(m, fmt) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (m) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) seq_printf(m, fmt); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct pg_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct seq_file *seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) const struct addr_marker *marker;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) unsigned long start_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) unsigned level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) u64 current_prot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) bool check_wx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) unsigned long wx_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) const char *current_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct prot_bits {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) u64 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) u64 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) const char *set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) const char *clear;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) bool ro_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) bool nx_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static const struct prot_bits pte_bits[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) .mask = L_PTE_USER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) .val = L_PTE_USER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) .set = "USR",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) .clear = " ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) .mask = L_PTE_RDONLY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) .val = L_PTE_RDONLY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) .set = "ro",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) .clear = "RW",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) .ro_bit = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) .mask = L_PTE_XN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) .val = L_PTE_XN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) .set = "NX",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) .clear = "x ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) .nx_bit = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) .mask = L_PTE_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) .val = L_PTE_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) .set = "SHD",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) .clear = " ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) .mask = L_PTE_MT_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) .val = L_PTE_MT_UNCACHED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) .set = "SO/UNCACHED",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) .mask = L_PTE_MT_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) .val = L_PTE_MT_BUFFERABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) .set = "MEM/BUFFERABLE/WC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) .mask = L_PTE_MT_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .val = L_PTE_MT_WRITETHROUGH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .set = "MEM/CACHED/WT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .mask = L_PTE_MT_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .val = L_PTE_MT_WRITEBACK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .set = "MEM/CACHED/WBRA",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #ifndef CONFIG_ARM_LPAE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) .mask = L_PTE_MT_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) .val = L_PTE_MT_MINICACHE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) .set = "MEM/MINICACHE",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) .mask = L_PTE_MT_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .val = L_PTE_MT_WRITEALLOC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .set = "MEM/CACHED/WBWA",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) .mask = L_PTE_MT_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) .val = L_PTE_MT_DEV_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) .set = "DEV/SHARED",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #ifndef CONFIG_ARM_LPAE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) .mask = L_PTE_MT_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) .val = L_PTE_MT_DEV_NONSHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .set = "DEV/NONSHARED",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .mask = L_PTE_MT_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .val = L_PTE_MT_DEV_WC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) .set = "DEV/WC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) .mask = L_PTE_MT_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) .val = L_PTE_MT_DEV_CACHED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) .set = "DEV/CACHED",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static const struct prot_bits section_bits[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #ifdef CONFIG_ARM_LPAE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) .mask = PMD_SECT_USER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .val = PMD_SECT_USER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .set = "USR",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) .mask = L_PMD_SECT_RDONLY | PMD_SECT_AP2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .val = L_PMD_SECT_RDONLY | PMD_SECT_AP2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .set = "ro",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) .clear = "RW",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) .ro_bit = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #elif __LINUX_ARM_ARCH__ >= 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) .mask = PMD_SECT_APX | PMD_SECT_AP_READ | PMD_SECT_AP_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) .val = PMD_SECT_APX | PMD_SECT_AP_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) .set = " ro",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .ro_bit = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) .mask = PMD_SECT_APX | PMD_SECT_AP_READ | PMD_SECT_AP_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) .val = PMD_SECT_AP_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .set = " RW",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) .mask = PMD_SECT_APX | PMD_SECT_AP_READ | PMD_SECT_AP_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) .val = PMD_SECT_AP_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) .set = "USR ro",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .mask = PMD_SECT_APX | PMD_SECT_AP_READ | PMD_SECT_AP_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) .val = PMD_SECT_AP_READ | PMD_SECT_AP_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) .set = "USR RW",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #else /* ARMv4/ARMv5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /* These are approximate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) .mask = PMD_SECT_AP_READ | PMD_SECT_AP_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) .val = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) .set = " ro",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) .ro_bit = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) .mask = PMD_SECT_AP_READ | PMD_SECT_AP_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) .val = PMD_SECT_AP_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) .set = " RW",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) .mask = PMD_SECT_AP_READ | PMD_SECT_AP_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .val = PMD_SECT_AP_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) .set = "USR ro",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) .mask = PMD_SECT_AP_READ | PMD_SECT_AP_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) .val = PMD_SECT_AP_READ | PMD_SECT_AP_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) .set = "USR RW",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .mask = PMD_SECT_XN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) .val = PMD_SECT_XN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) .set = "NX",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) .clear = "x ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) .nx_bit = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) .mask = PMD_SECT_S,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) .val = PMD_SECT_S,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) .set = "SHD",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) .clear = " ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct pg_level {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) const struct prot_bits *bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) size_t num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) u64 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) const struct prot_bits *ro_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) const struct prot_bits *nx_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static struct pg_level pg_level[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }, { /* pgd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }, { /* p4d */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }, { /* pud */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }, { /* pmd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) .bits = section_bits,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) .num = ARRAY_SIZE(section_bits),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }, { /* pte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) .bits = pte_bits,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) .num = ARRAY_SIZE(pte_bits),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static void dump_prot(struct pg_state *st, const struct prot_bits *bits, size_t num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) unsigned i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) for (i = 0; i < num; i++, bits++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) const char *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if ((st->current_prot & bits->mask) == bits->val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) s = bits->set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) s = bits->clear;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) pt_dump_seq_printf(st->seq, " %s", s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) static void note_prot_wx(struct pg_state *st, unsigned long addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (!st->check_wx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if ((st->current_prot & pg_level[st->level].ro_bit->mask) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) pg_level[st->level].ro_bit->val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if ((st->current_prot & pg_level[st->level].nx_bit->mask) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) pg_level[st->level].nx_bit->val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) WARN_ONCE(1, "arm/mm: Found insecure W+X mapping at address %pS\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) (void *)st->start_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) st->wx_pages += (addr - st->start_address) / PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static void note_page(struct pg_state *st, unsigned long addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) unsigned int level, u64 val, const char *domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static const char units[] = "KMGTPE";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) u64 prot = val & pg_level[level].mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (!st->level) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) st->level = level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) st->current_prot = prot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) st->current_domain = domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) pt_dump_seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) } else if (prot != st->current_prot || level != st->level ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) domain != st->current_domain ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) addr >= st->marker[1].start_address) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) const char *unit = units;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) unsigned long delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (st->current_prot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) note_prot_wx(st, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) pt_dump_seq_printf(st->seq, "0x%08lx-0x%08lx ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) st->start_address, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) delta = (addr - st->start_address) >> 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) while (!(delta & 1023) && unit[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) delta >>= 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) unit++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) pt_dump_seq_printf(st->seq, "%9lu%c", delta, *unit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (st->current_domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) pt_dump_seq_printf(st->seq, " %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) st->current_domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (pg_level[st->level].bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) dump_prot(st, pg_level[st->level].bits, pg_level[st->level].num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) pt_dump_seq_printf(st->seq, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (addr >= st->marker[1].start_address) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) st->marker++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) pt_dump_seq_printf(st->seq, "---[ %s ]---\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) st->marker->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) st->start_address = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) st->current_prot = prot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) st->current_domain = domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) st->level = level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) static void walk_pte(struct pg_state *st, pmd_t *pmd, unsigned long start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) const char *domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) pte_t *pte = pte_offset_kernel(pmd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) unsigned i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) for (i = 0; i < PTRS_PER_PTE; i++, pte++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) addr = start + i * PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) note_page(st, addr, 5, pte_val(*pte), domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) static const char *get_domain_name(pmd_t *pmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) #ifndef CONFIG_ARM_LPAE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) switch (pmd_val(*pmd) & PMD_DOMAIN_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) case PMD_DOMAIN(DOMAIN_KERNEL):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) return "KERNEL ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) case PMD_DOMAIN(DOMAIN_USER):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return "USER ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) case PMD_DOMAIN(DOMAIN_IO):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) return "IO ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) case PMD_DOMAIN(DOMAIN_VECTORS):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return "VECTORS";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return "unknown";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) static void walk_pmd(struct pg_state *st, pud_t *pud, unsigned long start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) pmd_t *pmd = pmd_offset(pud, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) unsigned i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) const char *domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) for (i = 0; i < PTRS_PER_PMD; i++, pmd++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) addr = start + i * PMD_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) domain = get_domain_name(pmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (pmd_none(*pmd) || pmd_large(*pmd) || !pmd_present(*pmd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) note_page(st, addr, 3, pmd_val(*pmd), domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) walk_pte(st, pmd, addr, domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (SECTION_SIZE < PMD_SIZE && pmd_large(pmd[1])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) addr += SECTION_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) pmd++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) domain = get_domain_name(pmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) note_page(st, addr, 4, pmd_val(*pmd), domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) static void walk_pud(struct pg_state *st, p4d_t *p4d, unsigned long start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) pud_t *pud = pud_offset(p4d, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) unsigned i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) for (i = 0; i < PTRS_PER_PUD; i++, pud++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) addr = start + i * PUD_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (!pud_none(*pud)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) walk_pmd(st, pud, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) note_page(st, addr, 3, pud_val(*pud), NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) static void walk_p4d(struct pg_state *st, pgd_t *pgd, unsigned long start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) p4d_t *p4d = p4d_offset(pgd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) unsigned i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) for (i = 0; i < PTRS_PER_P4D; i++, p4d++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) addr = start + i * P4D_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (!p4d_none(*p4d)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) walk_pud(st, p4d, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) note_page(st, addr, 2, p4d_val(*p4d), NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) static void walk_pgd(struct pg_state *st, struct mm_struct *mm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) unsigned long start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) pgd_t *pgd = pgd_offset(mm, 0UL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) unsigned i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) for (i = 0; i < PTRS_PER_PGD; i++, pgd++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) addr = start + i * PGDIR_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (!pgd_none(*pgd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) walk_p4d(st, pgd, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) note_page(st, addr, 1, pgd_val(*pgd), NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) void ptdump_walk_pgd(struct seq_file *m, struct ptdump_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) struct pg_state st = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) .seq = m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) .marker = info->markers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) .check_wx = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) walk_pgd(&st, info->mm, info->base_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) note_page(&st, 0, 0, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) static void ptdump_initialize(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) unsigned i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) for (i = 0; i < ARRAY_SIZE(pg_level); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (pg_level[i].bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) for (j = 0; j < pg_level[i].num; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) pg_level[i].mask |= pg_level[i].bits[j].mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (pg_level[i].bits[j].ro_bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) pg_level[i].ro_bit = &pg_level[i].bits[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (pg_level[i].bits[j].nx_bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) pg_level[i].nx_bit = &pg_level[i].bits[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) address_markers[2].start_address = VMALLOC_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) static struct ptdump_info kernel_ptdump_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) .mm = &init_mm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) .markers = address_markers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) .base_addr = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) void ptdump_check_wx(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) struct pg_state st = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) .seq = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) .marker = (struct addr_marker[]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) { 0, NULL},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) { -1, NULL},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) .check_wx = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) walk_pgd(&st, &init_mm, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) note_page(&st, 0, 0, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (st.wx_pages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) pr_warn("Checked W+X mappings: FAILED, %lu W+X pages found\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) st.wx_pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) pr_info("Checked W+X mappings: passed, no W+X pages found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) static int ptdump_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) ptdump_initialize();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) ptdump_debugfs_register(&kernel_ptdump_info, "kernel_page_tables");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) __initcall(ptdump_init);