History

mm: ptdump: reduce level numbers by 1 in note_page()

Rather than having to increment the 'depth' number by 1 in ptdump_hole(), let's change the meaning of 'level' in note_page() since that makes the code simplier. Note that for x86, the level numbers were previously increased by 1 in commit 45dcd2091363 ("x86/mm/dump_pagetables: Fix printout of p4d level") and the comment "Bit 7 has a different meaning" was not updated, so this change also makes the code match the comment again.

Steven Price committed 6 years ago

Commit f8f0d0b1 parent 9c7869c4 files · +22 −20Browse files

Unified · Split

4 files
  1. arch/arm64/mm/dump.c +3 −3
  2. arch/x86/mm/dump_pagetables.c +10 −9
  3. include/linux/ptdump.h +1 −0
  4. mm/ptdump.c +8 −8
arch/arm64/mm/dump.c+3−3
@@ -176,8 +176,7 @@ struct pg_level { · 175 unmodified lines
176};176};
177 177
178static struct pg_level pg_level[] = {178static struct pg_level pg_level[] = {
179 {179 { /* pgd */
180 }, { /* pgd */
181 .name = "PGD",180 .name = "PGD",
182 .bits = pte_bits,181 .bits = pte_bits,
183 .num = ARRAY_SIZE(pte_bits),182 .num = ARRAY_SIZE(pte_bits),
@@ -257,7 +256,7 @@ static void note_page(struct ptdump_state *pt_st, unsigned long addr, int level, · 73 unmodified lines
257 if (level >= 0)256 if (level >= 0)
258 prot = val & pg_level[level].mask;257 prot = val & pg_level[level].mask;
259 258
260 if (!st->level) {259 if (st->level == -1) {
261 st->level = level;260 st->level = level;
262 st->current_prot = prot;261 st->current_prot = prot;
263 st->start_address = addr;262 st->start_address = addr;
@@ -351,6 +350,7 @@ void ptdump_check_wx(void) · 87 unmodified lines
351 { 0, NULL},350 { 0, NULL},
352 { -1, NULL},351 { -1, NULL},
353 },352 },
353 .level = -1,
354 .check_wx = true,354 .check_wx = true,
355 .ptdump = {355 .ptdump = {
356 .note_page = note_page,356 .note_page = note_page,
arch/x86/mm/dump_pagetables.c+10−9
@@ -180,7 +180,7 @@ static struct addr_marker address_markers[] = { · 179 unmodified lines
180static void printk_prot(struct seq_file *m, pgprotval_t pr, int level, bool dmsg)180static void printk_prot(struct seq_file *m, pgprotval_t pr, int level, bool dmsg)
181{181{
182 static const char * const level_name[] =182 static const char * const level_name[] =
183 { "cr3", "pgd", "p4d", "pud", "pmd", "pte" };183 { "pgd", "p4d", "pud", "pmd", "pte" };
184 184
185 if (!(pr & _PAGE_PRESENT)) {185 if (!(pr & _PAGE_PRESENT)) {
186 /* Not present */186 /* Not present */
@@ -204,12 +204,12 @@ static void printk_prot(struct seq_file *m, pgprotval_t pr, int level, bool dmsg · 17 unmodified lines
204 pt_dump_cont_printf(m, dmsg, " ");204 pt_dump_cont_printf(m, dmsg, " ");
205 205
206 /* Bit 7 has a different meaning on level 3 vs 4 */206 /* Bit 7 has a different meaning on level 3 vs 4 */
207 if (level <= 4 && pr & _PAGE_PSE)207 if (level <= 3 && pr & _PAGE_PSE)
208 pt_dump_cont_printf(m, dmsg, "PSE ");208 pt_dump_cont_printf(m, dmsg, "PSE ");
209 else209 else
210 pt_dump_cont_printf(m, dmsg, " ");210 pt_dump_cont_printf(m, dmsg, " ");
211 if ((level == 5 && pr & _PAGE_PAT) ||211 if ((level == 4 && pr & _PAGE_PAT) ||
212 ((level == 4 || level == 3) && pr & _PAGE_PAT_LARGE))212 ((level == 3 || level == 2) && pr & _PAGE_PAT_LARGE))
213 pt_dump_cont_printf(m, dmsg, "PAT ");213 pt_dump_cont_printf(m, dmsg, "PAT ");
214 else214 else
215 pt_dump_cont_printf(m, dmsg, " ");215 pt_dump_cont_printf(m, dmsg, " ");
@@ -271,15 +271,15 @@ static void note_page(struct ptdump_state *pt_st, unsigned long addr, int level, · 55 unmodified lines
271 271
272 new_prot = val & PTE_FLAGS_MASK;272 new_prot = val & PTE_FLAGS_MASK;
273 273
274 if (level > 1) {274 if (level > 0) {
275 new_eff = effective_prot(st->prot_levels[level - 2],275 new_eff = effective_prot(st->prot_levels[level - 1],
276 new_prot);276 new_prot);
277 } else {277 } else {
278 new_eff = new_prot;278 new_eff = new_prot;
279 }279 }
280 280
281 if (level > 0)281 if (level >= 0)
282 st->prot_levels[level - 1] = new_eff;282 st->prot_levels[level] = new_eff;
283 283
284 /*284 /*
285 * If we have a "break" in the series, we need to flush the state that285 * If we have a "break" in the series, we need to flush the state that
@@ -289,7 +289,7 @@ static void note_page(struct ptdump_state *pt_st, unsigned long addr, int level, · 3 unmodified lines
289 cur = st->current_prot;289 cur = st->current_prot;
290 eff = st->effective_prot;290 eff = st->effective_prot;
291 291
292 if (!st->level) {292 if (st->level == -1) {
293 /* First entry */293 /* First entry */
294 st->current_prot = new_prot;294 st->current_prot = new_prot;
295 st->effective_prot = new_eff;295 st->effective_prot = new_eff;
@@ -380,6 +380,7 @@ static void ptdump_walk_pgd_level_core(struct seq_file *m, pgd_t *pgd, · 84 unmodified lines
380 .note_page = note_page,380 .note_page = note_page,
381 .range = ptdump_ranges381 .range = ptdump_ranges
382 },382 },
383 .level = -1,
383 .to_dmesg = dmesg,384 .to_dmesg = dmesg,
384 .check_wx = checkwx,385 .check_wx = checkwx,
385 .seq = m386 .seq = m
include/linux/ptdump.h+1−0
@@ -11,6 +11,7 @@ struct ptdump_range { · 10 unmodified lines
11};11};
12 12
13struct ptdump_state {13struct ptdump_state {
14 /* level is 0:PGD to 4:PTE, or -1 if unknown */
14 void (*note_page)(struct ptdump_state *st, unsigned long addr,15 void (*note_page)(struct ptdump_state *st, unsigned long addr,
15 int level, unsigned long val);16 int level, unsigned long val);
16 const struct ptdump_range *range;17 const struct ptdump_range *range;
mm/ptdump.c+8−8
@@ -17,7 +17,7 @@ static inline int note_kasan_page_table(struct mm_walk *walk, · 16 unmodified lines
17{17{
18 struct ptdump_state *st = walk->private;18 struct ptdump_state *st = walk->private;
19 19
20 st->note_page(st, addr, 5, pte_val(kasan_early_shadow_pte[0]));20 st->note_page(st, addr, 4, pte_val(kasan_early_shadow_pte[0]));
21 21
22 walk->action = ACTION_CONTINUE;22 walk->action = ACTION_CONTINUE;
23 23
@@ -37,7 +37,7 @@ static int ptdump_pgd_entry(pgd_t *pgd, unsigned long addr, · 13 unmodified lines
37#endif37#endif
38 38
39 if (pgd_leaf(val))39 if (pgd_leaf(val))
40 st->note_page(st, addr, 1, pgd_val(val));40 st->note_page(st, addr, 0, pgd_val(val));
41 41
42 return 0;42 return 0;
43}43}
@@ -54,7 +54,7 @@ static int ptdump_p4d_entry(p4d_t *p4d, unsigned long addr, · 10 unmodified lines
54#endif54#endif
55 55
56 if (p4d_leaf(val))56 if (p4d_leaf(val))
57 st->note_page(st, addr, 2, p4d_val(val));57 st->note_page(st, addr, 1, p4d_val(val));
58 58
59 return 0;59 return 0;
60}60}
@@ -71,7 +71,7 @@ static int ptdump_pud_entry(pud_t *pud, unsigned long addr, · 10 unmodified lines
71#endif71#endif
72 72
73 if (pud_leaf(val))73 if (pud_leaf(val))
74 st->note_page(st, addr, 3, pud_val(val));74 st->note_page(st, addr, 2, pud_val(val));
75 75
76 return 0;76 return 0;
77}77}
@@ -88,7 +88,7 @@ static int ptdump_pmd_entry(pmd_t *pmd, unsigned long addr, · 10 unmodified lines
88#endif88#endif
89 89
90 if (pmd_leaf(val))90 if (pmd_leaf(val))
91 st->note_page(st, addr, 4, pmd_val(val));91 st->note_page(st, addr, 3, pmd_val(val));
92 92
93 return 0;93 return 0;
94}94}
@@ -98,7 +98,7 @@ static int ptdump_pte_entry(pte_t *pte, unsigned long addr, · 3 unmodified lines
98{98{
99 struct ptdump_state *st = walk->private;99 struct ptdump_state *st = walk->private;
100 100
101 st->note_page(st, addr, 5, pte_val(READ_ONCE(*pte)));101 st->note_page(st, addr, 4, pte_val(READ_ONCE(*pte)));
102 102
103 return 0;103 return 0;
104}104}
@@ -108,7 +108,7 @@ static int ptdump_hole(unsigned long addr, unsigned long next, · 3 unmodified lines
108{108{
109 struct ptdump_state *st = walk->private;109 struct ptdump_state *st = walk->private;
110 110
111 st->note_page(st, addr, depth + 1, 0);111 st->note_page(st, addr, depth, 0);
112 112
113 return 0;113 return 0;
114}114}
@@ -135,5 +135,5 @@ void ptdump_walk_pgd(struct ptdump_state *st, struct mm_struct *mm) · 20 unmodified lines
135 up_read(&mm->mmap_sem);135 up_read(&mm->mmap_sem);
136 136
137 /* Flush out the last page */137 /* Flush out the last page */
138 st->note_page(st, 0, 0, 0);138 st->note_page(st, 0, -1, 0);
139}139}