Commit da25e628 authored by Toshi Kani's avatar Toshi Kani Committed by Thomas Gleixner

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: default avatarRobert Elliott <elliott@hpe.com>
Signed-off-by: default avatarToshi 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.comSigned-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent bbac8c6d
...@@ -155,7 +155,7 @@ static void printk_prot(struct seq_file *m, pgprot_t prot, int level, bool dmsg) ...@@ -155,7 +155,7 @@ static void printk_prot(struct seq_file *m, pgprot_t prot, int level, bool dmsg)
pt_dump_cont_printf(m, dmsg, " "); pt_dump_cont_printf(m, dmsg, " ");
if ((level == 4 && pr & _PAGE_PAT) || if ((level == 4 && pr & _PAGE_PAT) ||
((level == 3 || level == 2) && pr & _PAGE_PAT_LARGE)) ((level == 3 || level == 2) && pr & _PAGE_PAT_LARGE))
pt_dump_cont_printf(m, dmsg, "pat "); pt_dump_cont_printf(m, dmsg, "PAT ");
else else
pt_dump_cont_printf(m, dmsg, " "); pt_dump_cont_printf(m, dmsg, " ");
if (pr & _PAGE_GLOBAL) if (pr & _PAGE_GLOBAL)
...@@ -198,8 +198,8 @@ static void note_page(struct seq_file *m, struct pg_state *st, ...@@ -198,8 +198,8 @@ static void note_page(struct seq_file *m, struct pg_state *st,
* we have now. "break" is either changing perms, levels or * we have now. "break" is either changing perms, levels or
* address space marker. * address space marker.
*/ */
prot = pgprot_val(new_prot) & PTE_FLAGS_MASK; prot = pgprot_val(new_prot);
cur = pgprot_val(st->current_prot) & PTE_FLAGS_MASK; cur = pgprot_val(st->current_prot);
if (!st->level) { if (!st->level) {
/* First entry */ /* First entry */
...@@ -269,13 +269,13 @@ static void walk_pte_level(struct seq_file *m, struct pg_state *st, pmd_t addr, ...@@ -269,13 +269,13 @@ static void walk_pte_level(struct seq_file *m, struct pg_state *st, pmd_t addr,
{ {
int i; int i;
pte_t *start; pte_t *start;
pgprotval_t prot;
start = (pte_t *) pmd_page_vaddr(addr); start = (pte_t *) pmd_page_vaddr(addr);
for (i = 0; i < PTRS_PER_PTE; i++) { for (i = 0; i < PTRS_PER_PTE; i++) {
pgprot_t prot = pte_pgprot(*start); prot = pte_flags(*start);
st->current_address = normalize_addr(P + i * PTE_LEVEL_MULT); st->current_address = normalize_addr(P + i * PTE_LEVEL_MULT);
note_page(m, st, prot, 4); note_page(m, st, __pgprot(prot), 4);
start++; start++;
} }
} }
...@@ -287,18 +287,19 @@ static void walk_pmd_level(struct seq_file *m, struct pg_state *st, pud_t addr, ...@@ -287,18 +287,19 @@ static void walk_pmd_level(struct seq_file *m, struct pg_state *st, pud_t addr,
{ {
int i; int i;
pmd_t *start; pmd_t *start;
pgprotval_t prot;
start = (pmd_t *) pud_page_vaddr(addr); start = (pmd_t *) pud_page_vaddr(addr);
for (i = 0; i < PTRS_PER_PMD; i++) { for (i = 0; i < PTRS_PER_PMD; i++) {
st->current_address = normalize_addr(P + i * PMD_LEVEL_MULT); st->current_address = normalize_addr(P + i * PMD_LEVEL_MULT);
if (!pmd_none(*start)) { if (!pmd_none(*start)) {
pgprotval_t prot = pmd_val(*start) & PTE_FLAGS_MASK; if (pmd_large(*start) || !pmd_present(*start)) {
prot = pmd_flags(*start);
if (pmd_large(*start) || !pmd_present(*start))
note_page(m, st, __pgprot(prot), 3); note_page(m, st, __pgprot(prot), 3);
else } else {
walk_pte_level(m, st, *start, walk_pte_level(m, st, *start,
P + i * PMD_LEVEL_MULT); P + i * PMD_LEVEL_MULT);
}
} else } else
note_page(m, st, __pgprot(0), 3); note_page(m, st, __pgprot(0), 3);
start++; start++;
...@@ -318,19 +319,20 @@ static void walk_pud_level(struct seq_file *m, struct pg_state *st, pgd_t addr, ...@@ -318,19 +319,20 @@ static void walk_pud_level(struct seq_file *m, struct pg_state *st, pgd_t addr,
{ {
int i; int i;
pud_t *start; pud_t *start;
pgprotval_t prot;
start = (pud_t *) pgd_page_vaddr(addr); start = (pud_t *) pgd_page_vaddr(addr);
for (i = 0; i < PTRS_PER_PUD; i++) { for (i = 0; i < PTRS_PER_PUD; i++) {
st->current_address = normalize_addr(P + i * PUD_LEVEL_MULT); st->current_address = normalize_addr(P + i * PUD_LEVEL_MULT);
if (!pud_none(*start)) { if (!pud_none(*start)) {
pgprotval_t prot = pud_val(*start) & PTE_FLAGS_MASK; if (pud_large(*start) || !pud_present(*start)) {
prot = pud_flags(*start);
if (pud_large(*start) || !pud_present(*start))
note_page(m, st, __pgprot(prot), 2); note_page(m, st, __pgprot(prot), 2);
else } else {
walk_pmd_level(m, st, *start, walk_pmd_level(m, st, *start,
P + i * PUD_LEVEL_MULT); P + i * PUD_LEVEL_MULT);
}
} else } else
note_page(m, st, __pgprot(0), 2); note_page(m, st, __pgprot(0), 2);
...@@ -351,6 +353,7 @@ void ptdump_walk_pgd_level(struct seq_file *m, pgd_t *pgd) ...@@ -351,6 +353,7 @@ void ptdump_walk_pgd_level(struct seq_file *m, pgd_t *pgd)
#else #else
pgd_t *start = swapper_pg_dir; pgd_t *start = swapper_pg_dir;
#endif #endif
pgprotval_t prot;
int i; int i;
struct pg_state st = {}; struct pg_state st = {};
...@@ -362,13 +365,13 @@ void ptdump_walk_pgd_level(struct seq_file *m, pgd_t *pgd) ...@@ -362,13 +365,13 @@ void ptdump_walk_pgd_level(struct seq_file *m, pgd_t *pgd)
for (i = 0; i < PTRS_PER_PGD; i++) { for (i = 0; i < PTRS_PER_PGD; i++) {
st.current_address = normalize_addr(i * PGD_LEVEL_MULT); st.current_address = normalize_addr(i * PGD_LEVEL_MULT);
if (!pgd_none(*start)) { if (!pgd_none(*start)) {
pgprotval_t prot = pgd_val(*start) & PTE_FLAGS_MASK; if (pgd_large(*start) || !pgd_present(*start)) {
prot = pgd_flags(*start);
if (pgd_large(*start) || !pgd_present(*start))
note_page(m, &st, __pgprot(prot), 1); note_page(m, &st, __pgprot(prot), 1);
else } else {
walk_pud_level(m, &st, *start, walk_pud_level(m, &st, *start,
i * PGD_LEVEL_MULT); i * PGD_LEVEL_MULT);
}
} else } else
note_page(m, &st, __pgprot(0), 1); note_page(m, &st, __pgprot(0), 1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment