Skip to content

Commit da25e62

Browse files
toshikaniKAGA-KOKO
authored andcommitted
x86/mm: Fix page table dump to show PAT bit
/sys/kernel/debug/kernel_page_tables does not show the PAT bit for PUD/PMD mappings. This is because walk_pud_level(), walk_pmd_level() and note_page() mask the flags with PTE_FLAGS_MASK, which does not cover their PAT bit, _PAGE_PAT_LARGE. Fix it by replacing the use of PTE_FLAGS_MASK with p?d_flags(), which masks the flags properly. Also change to show the PAT bit as "PAT" to be consistent with other bits. Reported-by: Robert Elliott <elliott@hpe.com> Signed-off-by: Toshi Kani <toshi.kani@hpe.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Juergen Gross <jgross@suse.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Borislav Petkov <bp@alien8.de> Cc: Konrad Wilk <konrad.wilk@oracle.com> Cc: Robert Elliot <elliott@hpe.com> Cc: linux-mm@kvack.org Link: http://lkml.kernel.org/r/1442514264-12475-7-git-send-email-toshi.kani@hpe.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
1 parent bbac8c6 commit da25e62

File tree

1 file changed

+21
-18
lines changed

1 file changed

+21
-18
lines changed

arch/x86/mm/dump_pagetables.c

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ static void printk_prot(struct seq_file *m, pgprot_t prot, int level, bool dmsg)
155155
pt_dump_cont_printf(m, dmsg, " ");
156156
if ((level == 4 && pr & _PAGE_PAT) ||
157157
((level == 3 || level == 2) && pr & _PAGE_PAT_LARGE))
158-
pt_dump_cont_printf(m, dmsg, "pat ");
158+
pt_dump_cont_printf(m, dmsg, "PAT ");
159159
else
160160
pt_dump_cont_printf(m, dmsg, " ");
161161
if (pr & _PAGE_GLOBAL)
@@ -198,8 +198,8 @@ static void note_page(struct seq_file *m, struct pg_state *st,
198198
* we have now. "break" is either changing perms, levels or
199199
* address space marker.
200200
*/
201-
prot = pgprot_val(new_prot) & PTE_FLAGS_MASK;
202-
cur = pgprot_val(st->current_prot) & PTE_FLAGS_MASK;
201+
prot = pgprot_val(new_prot);
202+
cur = pgprot_val(st->current_prot);
203203

204204
if (!st->level) {
205205
/* First entry */
@@ -269,13 +269,13 @@ static void walk_pte_level(struct seq_file *m, struct pg_state *st, pmd_t addr,
269269
{
270270
int i;
271271
pte_t *start;
272+
pgprotval_t prot;
272273

273274
start = (pte_t *) pmd_page_vaddr(addr);
274275
for (i = 0; i < PTRS_PER_PTE; i++) {
275-
pgprot_t prot = pte_pgprot(*start);
276-
276+
prot = pte_flags(*start);
277277
st->current_address = normalize_addr(P + i * PTE_LEVEL_MULT);
278-
note_page(m, st, prot, 4);
278+
note_page(m, st, __pgprot(prot), 4);
279279
start++;
280280
}
281281
}
@@ -287,18 +287,19 @@ static void walk_pmd_level(struct seq_file *m, struct pg_state *st, pud_t addr,
287287
{
288288
int i;
289289
pmd_t *start;
290+
pgprotval_t prot;
290291

291292
start = (pmd_t *) pud_page_vaddr(addr);
292293
for (i = 0; i < PTRS_PER_PMD; i++) {
293294
st->current_address = normalize_addr(P + i * PMD_LEVEL_MULT);
294295
if (!pmd_none(*start)) {
295-
pgprotval_t prot = pmd_val(*start) & PTE_FLAGS_MASK;
296-
297-
if (pmd_large(*start) || !pmd_present(*start))
296+
if (pmd_large(*start) || !pmd_present(*start)) {
297+
prot = pmd_flags(*start);
298298
note_page(m, st, __pgprot(prot), 3);
299-
else
299+
} else {
300300
walk_pte_level(m, st, *start,
301301
P + i * PMD_LEVEL_MULT);
302+
}
302303
} else
303304
note_page(m, st, __pgprot(0), 3);
304305
start++;
@@ -318,19 +319,20 @@ static void walk_pud_level(struct seq_file *m, struct pg_state *st, pgd_t addr,
318319
{
319320
int i;
320321
pud_t *start;
322+
pgprotval_t prot;
321323

322324
start = (pud_t *) pgd_page_vaddr(addr);
323325

324326
for (i = 0; i < PTRS_PER_PUD; i++) {
325327
st->current_address = normalize_addr(P + i * PUD_LEVEL_MULT);
326328
if (!pud_none(*start)) {
327-
pgprotval_t prot = pud_val(*start) & PTE_FLAGS_MASK;
328-
329-
if (pud_large(*start) || !pud_present(*start))
329+
if (pud_large(*start) || !pud_present(*start)) {
330+
prot = pud_flags(*start);
330331
note_page(m, st, __pgprot(prot), 2);
331-
else
332+
} else {
332333
walk_pmd_level(m, st, *start,
333334
P + i * PUD_LEVEL_MULT);
335+
}
334336
} else
335337
note_page(m, st, __pgprot(0), 2);
336338

@@ -351,6 +353,7 @@ void ptdump_walk_pgd_level(struct seq_file *m, pgd_t *pgd)
351353
#else
352354
pgd_t *start = swapper_pg_dir;
353355
#endif
356+
pgprotval_t prot;
354357
int i;
355358
struct pg_state st = {};
356359

@@ -362,13 +365,13 @@ void ptdump_walk_pgd_level(struct seq_file *m, pgd_t *pgd)
362365
for (i = 0; i < PTRS_PER_PGD; i++) {
363366
st.current_address = normalize_addr(i * PGD_LEVEL_MULT);
364367
if (!pgd_none(*start)) {
365-
pgprotval_t prot = pgd_val(*start) & PTE_FLAGS_MASK;
366-
367-
if (pgd_large(*start) || !pgd_present(*start))
368+
if (pgd_large(*start) || !pgd_present(*start)) {
369+
prot = pgd_flags(*start);
368370
note_page(m, &st, __pgprot(prot), 1);
369-
else
371+
} else {
370372
walk_pud_level(m, &st, *start,
371373
i * PGD_LEVEL_MULT);
374+
}
372375
} else
373376
note_page(m, &st, __pgprot(0), 1);
374377

0 commit comments

Comments
 (0)