1 /*
2 * Debug helper to dump the current kernel pagetables of the system
3 * so that we can see what the various memory ranges are set to.
4 *
5 * (C) Copyright 2008 Intel Corporation
6 *
7 * Author: Arjan van de Ven <arjan@linux.intel.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; version 2
12 * of the License.
13 */
14
15 #include <linux/debugfs.h>
16 #include <linux/kasan.h>
17 #include <linux/mm.h>
18 #include <linux/init.h>
19 #include <linux/sched.h>
20 #include <linux/seq_file.h>
21 #include <linux/highmem.h>
22
23 #include <asm/pgtable.h>
24
25 /*
26 * The dumper groups pagetable entries of the same type into one, and for
27 * that it needs to keep some state when walking, and flush this state
28 * when a "break" in the continuity is found.
29 */
30 struct pg_state {
31 int level;
32 pgprot_t current_prot;
33 pgprotval_t effective_prot;
34 unsigned long start_address;
35 unsigned long current_address;
36 const struct addr_marker *marker;
37 unsigned long lines;
38 bool to_dmesg;
39 bool check_wx;
40 unsigned long wx_pages;
41 };
42
43 struct addr_marker {
44 unsigned long start_address;
45 const char *name;
46 unsigned long max_lines;
47 };
48
49 /* Address space markers hints */
50
51 #ifdef CONFIG_X86_64
52
53 enum address_markers_idx {
54 USER_SPACE_NR = 0,
55 KERNEL_SPACE_NR,
56 LOW_KERNEL_NR,
57 #if defined(CONFIG_MODIFY_LDT_SYSCALL) && defined(CONFIG_X86_5LEVEL)
58 LDT_NR,
59 #endif
60 VMALLOC_START_NR,
61 VMEMMAP_START_NR,
62 #ifdef CONFIG_KASAN
63 KASAN_SHADOW_START_NR,
64 KASAN_SHADOW_END_NR,
65 #endif
66 CPU_ENTRY_AREA_NR,
67 #if defined(CONFIG_MODIFY_LDT_SYSCALL) && !defined(CONFIG_X86_5LEVEL)
68 LDT_NR,
69 #endif
70 #ifdef CONFIG_X86_ESPFIX64
71 ESPFIX_START_NR,
72 #endif
73 #ifdef CONFIG_EFI
74 EFI_END_NR,
75 #endif
76 HIGH_KERNEL_NR,
77 MODULES_VADDR_NR,
78 MODULES_END_NR,
79 FIXADDR_START_NR,
80 END_OF_SPACE_NR,
81 };
82
83 static struct addr_marker address_markers[] = {
84 [USER_SPACE_NR] = { 0, "User Space" },
85 [KERNEL_SPACE_NR] = { (1UL << 63), "Kernel Space" },
86 [LOW_KERNEL_NR] = { 0UL, "Low Kernel Mapping" },
87 [VMALLOC_START_NR] = { 0UL, "vmalloc() Area" },
88 [VMEMMAP_START_NR] = { 0UL, "Vmemmap" },
89 #ifdef CONFIG_KASAN
90 /*
91 * These fields get initialized with the (dynamic)
92 * KASAN_SHADOW_{START,END} values in pt_dump_init().
93 */
94 [KASAN_SHADOW_START_NR] = { 0UL, "KASAN shadow" },
95 [KASAN_SHADOW_END_NR] = { 0UL, "KASAN shadow end" },
96 #endif
97 #ifdef CONFIG_MODIFY_LDT_SYSCALL
98 [LDT_NR] = { 0UL, "LDT remap" },
99 #endif
100 [CPU_ENTRY_AREA_NR] = { CPU_ENTRY_AREA_BASE,"CPU entry Area" },
101 #ifdef CONFIG_X86_ESPFIX64
102 [ESPFIX_START_NR] = { ESPFIX_BASE_ADDR, "ESPfix Area", 16 },
103 #endif
104 #ifdef CONFIG_EFI
105 [EFI_END_NR] = { EFI_VA_END, "EFI Runtime Services" },
106 #endif
107 [HIGH_KERNEL_NR] = { __START_KERNEL_map, "High Kernel Mapping" },
108 [MODULES_VADDR_NR] = { MODULES_VADDR, "Modules" },
109 [MODULES_END_NR] = { MODULES_END, "End Modules" },
110 [FIXADDR_START_NR] = { FIXADDR_START, "Fixmap Area" },
111 [END_OF_SPACE_NR] = { -1, NULL }
112 };
113
114 #define INIT_PGD ((pgd_t *) &init_top_pgt)
115
116 #else /* CONFIG_X86_64 */
117
118 enum address_markers_idx {
119 USER_SPACE_NR = 0,
120 KERNEL_SPACE_NR,
121 VMALLOC_START_NR,
122 VMALLOC_END_NR,
123 #ifdef CONFIG_HIGHMEM
124 PKMAP_BASE_NR,
125 #endif
126 #ifdef CONFIG_MODIFY_LDT_SYSCALL
127 LDT_NR,
128 #endif
129 CPU_ENTRY_AREA_NR,
130 FIXADDR_START_NR,
131 END_OF_SPACE_NR,
132 };
133
134 static struct addr_marker address_markers[] = {
135 [USER_SPACE_NR] = { 0, "User Space" },
136 [KERNEL_SPACE_NR] = { PAGE_OFFSET, "Kernel Mapping" },
137 [VMALLOC_START_NR] = { 0UL, "vmalloc() Area" },
138 [VMALLOC_END_NR] = { 0UL, "vmalloc() End" },
139 #ifdef CONFIG_HIGHMEM
140 [PKMAP_BASE_NR] = { 0UL, "Persistent kmap() Area" },
141 #endif
142 #ifdef CONFIG_MODIFY_LDT_SYSCALL
143 [LDT_NR] = { 0UL, "LDT remap" },
144 #endif
145 [CPU_ENTRY_AREA_NR] = { 0UL, "CPU entry area" },
146 [FIXADDR_START_NR] = { 0UL, "Fixmap area" },
147 [END_OF_SPACE_NR] = { -1, NULL }
148 };
149
150 #define INIT_PGD (swapper_pg_dir)
151
152 #endif /* !CONFIG_X86_64 */
153
154 /* Multipliers for offsets within the PTEs */
155 #define PTE_LEVEL_MULT (PAGE_SIZE)
156 #define PMD_LEVEL_MULT (PTRS_PER_PTE * PTE_LEVEL_MULT)
157 #define PUD_LEVEL_MULT (PTRS_PER_PMD * PMD_LEVEL_MULT)
158 #define P4D_LEVEL_MULT (PTRS_PER_PUD * PUD_LEVEL_MULT)
159 #define PGD_LEVEL_MULT (PTRS_PER_P4D * P4D_LEVEL_MULT)
160
161 #define pt_dump_seq_printf(m, to_dmesg, fmt, args...) \
162 ({ \
163 if (to_dmesg) \
164 printk(KERN_INFO fmt, ##args); \
165 else \
166 if (m) \
167 seq_printf(m, fmt, ##args); \
168 })
169
170 #define pt_dump_cont_printf(m, to_dmesg, fmt, args...) \
171 ({ \
172 if (to_dmesg) \
173 printk(KERN_CONT fmt, ##args); \
174 else \
175 if (m) \
176 seq_printf(m, fmt, ##args); \
177 })
178
179 /*
180 * Print a readable form of a pgprot_t to the seq_file
181 */
printk_prot(struct seq_file * m,pgprot_t prot,int level,bool dmsg)182 static void printk_prot(struct seq_file *m, pgprot_t prot, int level, bool dmsg)
183 {
184 pgprotval_t pr = pgprot_val(prot);
185 static const char * const level_name[] =
186 { "cr3", "pgd", "p4d", "pud", "pmd", "pte" };
187
188 if (!(pr & _PAGE_PRESENT)) {
189 /* Not present */
190 pt_dump_cont_printf(m, dmsg, " ");
191 } else {
192 if (pr & _PAGE_USER)
193 pt_dump_cont_printf(m, dmsg, "USR ");
194 else
195 pt_dump_cont_printf(m, dmsg, " ");
196 if (pr & _PAGE_RW)
197 pt_dump_cont_printf(m, dmsg, "RW ");
198 else
199 pt_dump_cont_printf(m, dmsg, "ro ");
200 if (pr & _PAGE_PWT)
201 pt_dump_cont_printf(m, dmsg, "PWT ");
202 else
203 pt_dump_cont_printf(m, dmsg, " ");
204 if (pr & _PAGE_PCD)
205 pt_dump_cont_printf(m, dmsg, "PCD ");
206 else
207 pt_dump_cont_printf(m, dmsg, " ");
208
209 /* Bit 7 has a different meaning on level 3 vs 4 */
210 if (level <= 4 && pr & _PAGE_PSE)
211 pt_dump_cont_printf(m, dmsg, "PSE ");
212 else
213 pt_dump_cont_printf(m, dmsg, " ");
214 if ((level == 5 && pr & _PAGE_PAT) ||
215 ((level == 4 || level == 3) && pr & _PAGE_PAT_LARGE))
216 pt_dump_cont_printf(m, dmsg, "PAT ");
217 else
218 pt_dump_cont_printf(m, dmsg, " ");
219 if (pr & _PAGE_GLOBAL)
220 pt_dump_cont_printf(m, dmsg, "GLB ");
221 else
222 pt_dump_cont_printf(m, dmsg, " ");
223 if (pr & _PAGE_NX)
224 pt_dump_cont_printf(m, dmsg, "NX ");
225 else
226 pt_dump_cont_printf(m, dmsg, "x ");
227 }
228 pt_dump_cont_printf(m, dmsg, "%s\n", level_name[level]);
229 }
230
231 /*
232 * On 64 bits, sign-extend the 48 bit address to 64 bit
233 */
normalize_addr(unsigned long u)234 static unsigned long normalize_addr(unsigned long u)
235 {
236 int shift;
237 if (!IS_ENABLED(CONFIG_X86_64))
238 return u;
239
240 shift = 64 - (__VIRTUAL_MASK_SHIFT + 1);
241 return (signed long)(u << shift) >> shift;
242 }
243
244 /*
245 * This function gets called on a break in a continuous series
246 * of PTE entries; the next one is different so we need to
247 * print what we collected so far.
248 */
note_page(struct seq_file * m,struct pg_state * st,pgprot_t new_prot,pgprotval_t new_eff,int level)249 static void note_page(struct seq_file *m, struct pg_state *st,
250 pgprot_t new_prot, pgprotval_t new_eff, int level)
251 {
252 pgprotval_t prot, cur, eff;
253 static const char units[] = "BKMGTPE";
254
255 /*
256 * If we have a "break" in the series, we need to flush the state that
257 * we have now. "break" is either changing perms, levels or
258 * address space marker.
259 */
260 prot = pgprot_val(new_prot);
261 cur = pgprot_val(st->current_prot);
262 eff = st->effective_prot;
263
264 if (!st->level) {
265 /* First entry */
266 st->current_prot = new_prot;
267 st->effective_prot = new_eff;
268 st->level = level;
269 st->marker = address_markers;
270 st->lines = 0;
271 pt_dump_seq_printf(m, st->to_dmesg, "---[ %s ]---\n",
272 st->marker->name);
273 } else if (prot != cur || new_eff != eff || level != st->level ||
274 st->current_address >= st->marker[1].start_address) {
275 const char *unit = units;
276 unsigned long delta;
277 int width = sizeof(unsigned long) * 2;
278
279 if (st->check_wx && (eff & _PAGE_RW) && !(eff & _PAGE_NX)) {
280 WARN_ONCE(1,
281 "x86/mm: Found insecure W+X mapping at address %p/%pS\n",
282 (void *)st->start_address,
283 (void *)st->start_address);
284 st->wx_pages += (st->current_address -
285 st->start_address) / PAGE_SIZE;
286 }
287
288 /*
289 * Now print the actual finished series
290 */
291 if (!st->marker->max_lines ||
292 st->lines < st->marker->max_lines) {
293 pt_dump_seq_printf(m, st->to_dmesg,
294 "0x%0*lx-0x%0*lx ",
295 width, st->start_address,
296 width, st->current_address);
297
298 delta = st->current_address - st->start_address;
299 while (!(delta & 1023) && unit[1]) {
300 delta >>= 10;
301 unit++;
302 }
303 pt_dump_cont_printf(m, st->to_dmesg, "%9lu%c ",
304 delta, *unit);
305 printk_prot(m, st->current_prot, st->level,
306 st->to_dmesg);
307 }
308 st->lines++;
309
310 /*
311 * We print markers for special areas of address space,
312 * such as the start of vmalloc space etc.
313 * This helps in the interpretation.
314 */
315 if (st->current_address >= st->marker[1].start_address) {
316 if (st->marker->max_lines &&
317 st->lines > st->marker->max_lines) {
318 unsigned long nskip =
319 st->lines - st->marker->max_lines;
320 pt_dump_seq_printf(m, st->to_dmesg,
321 "... %lu entr%s skipped ... \n",
322 nskip,
323 nskip == 1 ? "y" : "ies");
324 }
325 st->marker++;
326 st->lines = 0;
327 pt_dump_seq_printf(m, st->to_dmesg, "---[ %s ]---\n",
328 st->marker->name);
329 }
330
331 st->start_address = st->current_address;
332 st->current_prot = new_prot;
333 st->effective_prot = new_eff;
334 st->level = level;
335 }
336 }
337
effective_prot(pgprotval_t prot1,pgprotval_t prot2)338 static inline pgprotval_t effective_prot(pgprotval_t prot1, pgprotval_t prot2)
339 {
340 return (prot1 & prot2 & (_PAGE_USER | _PAGE_RW)) |
341 ((prot1 | prot2) & _PAGE_NX);
342 }
343
walk_pte_level(struct seq_file * m,struct pg_state * st,pmd_t addr,pgprotval_t eff_in,unsigned long P)344 static void walk_pte_level(struct seq_file *m, struct pg_state *st, pmd_t addr,
345 pgprotval_t eff_in, unsigned long P)
346 {
347 int i;
348 pte_t *pte;
349 pgprotval_t prot, eff;
350
351 for (i = 0; i < PTRS_PER_PTE; i++) {
352 st->current_address = normalize_addr(P + i * PTE_LEVEL_MULT);
353 pte = pte_offset_map(&addr, st->current_address);
354 prot = pte_flags(*pte);
355 eff = effective_prot(eff_in, prot);
356 note_page(m, st, __pgprot(prot), eff, 5);
357 pte_unmap(pte);
358 }
359 }
360 #ifdef CONFIG_KASAN
361
362 /*
363 * This is an optimization for KASAN=y case. Since all kasan page tables
364 * eventually point to the kasan_zero_page we could call note_page()
365 * right away without walking through lower level page tables. This saves
366 * us dozens of seconds (minutes for 5-level config) while checking for
367 * W+X mapping or reading kernel_page_tables debugfs file.
368 */
kasan_page_table(struct seq_file * m,struct pg_state * st,void * pt)369 static inline bool kasan_page_table(struct seq_file *m, struct pg_state *st,
370 void *pt)
371 {
372 if (__pa(pt) == __pa(kasan_zero_pmd) ||
373 (pgtable_l5_enabled() && __pa(pt) == __pa(kasan_zero_p4d)) ||
374 __pa(pt) == __pa(kasan_zero_pud)) {
375 pgprotval_t prot = pte_flags(kasan_zero_pte[0]);
376 note_page(m, st, __pgprot(prot), 0, 5);
377 return true;
378 }
379 return false;
380 }
381 #else
kasan_page_table(struct seq_file * m,struct pg_state * st,void * pt)382 static inline bool kasan_page_table(struct seq_file *m, struct pg_state *st,
383 void *pt)
384 {
385 return false;
386 }
387 #endif
388
389 #if PTRS_PER_PMD > 1
390
walk_pmd_level(struct seq_file * m,struct pg_state * st,pud_t addr,pgprotval_t eff_in,unsigned long P)391 static void walk_pmd_level(struct seq_file *m, struct pg_state *st, pud_t addr,
392 pgprotval_t eff_in, unsigned long P)
393 {
394 int i;
395 pmd_t *start, *pmd_start;
396 pgprotval_t prot, eff;
397
398 pmd_start = start = (pmd_t *)pud_page_vaddr(addr);
399 for (i = 0; i < PTRS_PER_PMD; i++) {
400 st->current_address = normalize_addr(P + i * PMD_LEVEL_MULT);
401 if (!pmd_none(*start)) {
402 prot = pmd_flags(*start);
403 eff = effective_prot(eff_in, prot);
404 if (pmd_large(*start) || !pmd_present(*start)) {
405 note_page(m, st, __pgprot(prot), eff, 4);
406 } else if (!kasan_page_table(m, st, pmd_start)) {
407 walk_pte_level(m, st, *start, eff,
408 P + i * PMD_LEVEL_MULT);
409 }
410 } else
411 note_page(m, st, __pgprot(0), 0, 4);
412 start++;
413 }
414 }
415
416 #else
417 #define walk_pmd_level(m,s,a,e,p) walk_pte_level(m,s,__pmd(pud_val(a)),e,p)
418 #define pud_large(a) pmd_large(__pmd(pud_val(a)))
419 #define pud_none(a) pmd_none(__pmd(pud_val(a)))
420 #endif
421
422 #if PTRS_PER_PUD > 1
423
walk_pud_level(struct seq_file * m,struct pg_state * st,p4d_t addr,pgprotval_t eff_in,unsigned long P)424 static void walk_pud_level(struct seq_file *m, struct pg_state *st, p4d_t addr,
425 pgprotval_t eff_in, unsigned long P)
426 {
427 int i;
428 pud_t *start, *pud_start;
429 pgprotval_t prot, eff;
430 pud_t *prev_pud = NULL;
431
432 pud_start = start = (pud_t *)p4d_page_vaddr(addr);
433
434 for (i = 0; i < PTRS_PER_PUD; i++) {
435 st->current_address = normalize_addr(P + i * PUD_LEVEL_MULT);
436 if (!pud_none(*start)) {
437 prot = pud_flags(*start);
438 eff = effective_prot(eff_in, prot);
439 if (pud_large(*start) || !pud_present(*start)) {
440 note_page(m, st, __pgprot(prot), eff, 3);
441 } else if (!kasan_page_table(m, st, pud_start)) {
442 walk_pmd_level(m, st, *start, eff,
443 P + i * PUD_LEVEL_MULT);
444 }
445 } else
446 note_page(m, st, __pgprot(0), 0, 3);
447
448 prev_pud = start;
449 start++;
450 }
451 }
452
453 #else
454 #define walk_pud_level(m,s,a,e,p) walk_pmd_level(m,s,__pud(p4d_val(a)),e,p)
455 #define p4d_large(a) pud_large(__pud(p4d_val(a)))
456 #define p4d_none(a) pud_none(__pud(p4d_val(a)))
457 #endif
458
walk_p4d_level(struct seq_file * m,struct pg_state * st,pgd_t addr,pgprotval_t eff_in,unsigned long P)459 static void walk_p4d_level(struct seq_file *m, struct pg_state *st, pgd_t addr,
460 pgprotval_t eff_in, unsigned long P)
461 {
462 int i;
463 p4d_t *start, *p4d_start;
464 pgprotval_t prot, eff;
465
466 if (PTRS_PER_P4D == 1)
467 return walk_pud_level(m, st, __p4d(pgd_val(addr)), eff_in, P);
468
469 p4d_start = start = (p4d_t *)pgd_page_vaddr(addr);
470
471 for (i = 0; i < PTRS_PER_P4D; i++) {
472 st->current_address = normalize_addr(P + i * P4D_LEVEL_MULT);
473 if (!p4d_none(*start)) {
474 prot = p4d_flags(*start);
475 eff = effective_prot(eff_in, prot);
476 if (p4d_large(*start) || !p4d_present(*start)) {
477 note_page(m, st, __pgprot(prot), eff, 2);
478 } else if (!kasan_page_table(m, st, p4d_start)) {
479 walk_pud_level(m, st, *start, eff,
480 P + i * P4D_LEVEL_MULT);
481 }
482 } else
483 note_page(m, st, __pgprot(0), 0, 2);
484
485 start++;
486 }
487 }
488
489 #define pgd_large(a) (pgtable_l5_enabled() ? pgd_large(a) : p4d_large(__p4d(pgd_val(a))))
490 #define pgd_none(a) (pgtable_l5_enabled() ? pgd_none(a) : p4d_none(__p4d(pgd_val(a))))
491
is_hypervisor_range(int idx)492 static inline bool is_hypervisor_range(int idx)
493 {
494 #ifdef CONFIG_X86_64
495 /*
496 * ffff800000000000 - ffff87ffffffffff is reserved for
497 * the hypervisor.
498 */
499 return (idx >= pgd_index(__PAGE_OFFSET) - 16) &&
500 (idx < pgd_index(__PAGE_OFFSET));
501 #else
502 return false;
503 #endif
504 }
505
ptdump_walk_pgd_level_core(struct seq_file * m,pgd_t * pgd,bool checkwx,bool dmesg)506 static void ptdump_walk_pgd_level_core(struct seq_file *m, pgd_t *pgd,
507 bool checkwx, bool dmesg)
508 {
509 pgd_t *start = INIT_PGD;
510 pgprotval_t prot, eff;
511 int i;
512 struct pg_state st = {};
513
514 if (pgd) {
515 start = pgd;
516 st.to_dmesg = dmesg;
517 }
518
519 st.check_wx = checkwx;
520 if (checkwx)
521 st.wx_pages = 0;
522
523 for (i = 0; i < PTRS_PER_PGD; i++) {
524 st.current_address = normalize_addr(i * PGD_LEVEL_MULT);
525 if (!pgd_none(*start) && !is_hypervisor_range(i)) {
526 prot = pgd_flags(*start);
527 #ifdef CONFIG_X86_PAE
528 eff = _PAGE_USER | _PAGE_RW;
529 #else
530 eff = prot;
531 #endif
532 if (pgd_large(*start) || !pgd_present(*start)) {
533 note_page(m, &st, __pgprot(prot), eff, 1);
534 } else {
535 walk_p4d_level(m, &st, *start, eff,
536 i * PGD_LEVEL_MULT);
537 }
538 } else
539 note_page(m, &st, __pgprot(0), 0, 1);
540
541 cond_resched();
542 start++;
543 }
544
545 /* Flush out the last page */
546 st.current_address = normalize_addr(PTRS_PER_PGD*PGD_LEVEL_MULT);
547 note_page(m, &st, __pgprot(0), 0, 0);
548 if (!checkwx)
549 return;
550 if (st.wx_pages)
551 pr_info("x86/mm: Checked W+X mappings: FAILED, %lu W+X pages found.\n",
552 st.wx_pages);
553 else
554 pr_info("x86/mm: Checked W+X mappings: passed, no W+X pages found.\n");
555 }
556
ptdump_walk_pgd_level(struct seq_file * m,pgd_t * pgd)557 void ptdump_walk_pgd_level(struct seq_file *m, pgd_t *pgd)
558 {
559 ptdump_walk_pgd_level_core(m, pgd, false, true);
560 }
561
ptdump_walk_pgd_level_debugfs(struct seq_file * m,pgd_t * pgd,bool user)562 void ptdump_walk_pgd_level_debugfs(struct seq_file *m, pgd_t *pgd, bool user)
563 {
564 #ifdef CONFIG_PAGE_TABLE_ISOLATION
565 if (user && static_cpu_has(X86_FEATURE_PTI))
566 pgd = kernel_to_user_pgdp(pgd);
567 #endif
568 ptdump_walk_pgd_level_core(m, pgd, false, false);
569 }
570 EXPORT_SYMBOL_GPL(ptdump_walk_pgd_level_debugfs);
571
ptdump_walk_user_pgd_level_checkwx(void)572 void ptdump_walk_user_pgd_level_checkwx(void)
573 {
574 #ifdef CONFIG_PAGE_TABLE_ISOLATION
575 pgd_t *pgd = INIT_PGD;
576
577 if (!(__supported_pte_mask & _PAGE_NX) ||
578 !static_cpu_has(X86_FEATURE_PTI))
579 return;
580
581 pr_info("x86/mm: Checking user space page tables\n");
582 pgd = kernel_to_user_pgdp(pgd);
583 ptdump_walk_pgd_level_core(NULL, pgd, true, false);
584 #endif
585 }
586
ptdump_walk_pgd_level_checkwx(void)587 void ptdump_walk_pgd_level_checkwx(void)
588 {
589 ptdump_walk_pgd_level_core(NULL, NULL, true, false);
590 }
591
pt_dump_init(void)592 static int __init pt_dump_init(void)
593 {
594 /*
595 * Various markers are not compile-time constants, so assign them
596 * here.
597 */
598 #ifdef CONFIG_X86_64
599 address_markers[LOW_KERNEL_NR].start_address = PAGE_OFFSET;
600 address_markers[VMALLOC_START_NR].start_address = VMALLOC_START;
601 address_markers[VMEMMAP_START_NR].start_address = VMEMMAP_START;
602 #ifdef CONFIG_MODIFY_LDT_SYSCALL
603 address_markers[LDT_NR].start_address = LDT_BASE_ADDR;
604 #endif
605 #ifdef CONFIG_KASAN
606 address_markers[KASAN_SHADOW_START_NR].start_address = KASAN_SHADOW_START;
607 address_markers[KASAN_SHADOW_END_NR].start_address = KASAN_SHADOW_END;
608 #endif
609 #endif
610 #ifdef CONFIG_X86_32
611 address_markers[VMALLOC_START_NR].start_address = VMALLOC_START;
612 address_markers[VMALLOC_END_NR].start_address = VMALLOC_END;
613 # ifdef CONFIG_HIGHMEM
614 address_markers[PKMAP_BASE_NR].start_address = PKMAP_BASE;
615 # endif
616 address_markers[FIXADDR_START_NR].start_address = FIXADDR_START;
617 address_markers[CPU_ENTRY_AREA_NR].start_address = CPU_ENTRY_AREA_BASE;
618 # ifdef CONFIG_MODIFY_LDT_SYSCALL
619 address_markers[LDT_NR].start_address = LDT_BASE_ADDR;
620 # endif
621 #endif
622 return 0;
623 }
624 __initcall(pt_dump_init);
625