aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorToshi Kani <toshi.kani@hpe.com>2015-09-17 14:24:19 -0400
committerThomas Gleixner <tglx@linutronix.de>2015-09-22 15:27:32 -0400
commitda25e628c4c231a281b1c1de3168a36ab9bfe473 (patch)
tree04c1ea8e88dc523fcce73ca4d8ae4358e8a818c1
parentbbac8c6deadab921f4b7d00ce675ffa4f358ec7f (diff)
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>
-rw-r--r--arch/x86/mm/dump_pagetables.c39
1 files changed, 21 insertions, 18 deletions
diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c
index f0cedf3395af..71ab2d741024 100644
--- a/arch/x86/mm/dump_pagetables.c
+++ b/arch/x86/mm/dump_pagetables.c
@@ -155,7 +155,7 @@ static void printk_prot(struct seq_file *m, pgprot_t prot, int level, bool dmsg)
155 pt_dump_cont_printf(m, dmsg, " "); 155 pt_dump_cont_printf(m, dmsg, " ");
156 if ((level == 4 && pr & _PAGE_PAT) || 156 if ((level == 4 && pr & _PAGE_PAT) ||
157 ((level == 3 || level == 2) && pr & _PAGE_PAT_LARGE)) 157 ((level == 3 || level == 2) && pr & _PAGE_PAT_LARGE))
158 pt_dump_cont_printf(m, dmsg, "pat "); 158 pt_dump_cont_printf(m, dmsg, "PAT ");
159 else 159 else
160 pt_dump_cont_printf(m, dmsg, " "); 160 pt_dump_cont_printf(m, dmsg, " ");
161 if (pr & _PAGE_GLOBAL) 161 if (pr & _PAGE_GLOBAL)
@@ -198,8 +198,8 @@ static void note_page(struct seq_file *m, struct pg_state *st,
198 * we have now. "break" is either changing perms, levels or 198 * we have now. "break" is either changing perms, levels or
199 * address space marker. 199 * address space marker.
200 */ 200 */
201 prot = pgprot_val(new_prot) & PTE_FLAGS_MASK; 201 prot = pgprot_val(new_prot);
202 cur = pgprot_val(st->current_prot) & PTE_FLAGS_MASK; 202 cur = pgprot_val(st->current_prot);
203 203
204 if (!st->level) { 204 if (!st->level) {
205 /* First entry */ 205 /* First entry */
@@ -269,13 +269,13 @@ static void walk_pte_level(struct seq_file *m, struct pg_state *st, pmd_t addr,
269{ 269{
270 int i; 270 int i;
271 pte_t *start; 271 pte_t *start;
272 pgprotval_t prot;
272 273
273 start = (pte_t *) pmd_page_vaddr(addr); 274 start = (pte_t *) pmd_page_vaddr(addr);
274 for (i = 0; i < PTRS_PER_PTE; i++) { 275 for (i = 0; i < PTRS_PER_PTE; i++) {
275 pgprot_t prot = pte_pgprot(*start); 276 prot = pte_flags(*start);
276
277 st->current_address = normalize_addr(P + i * PTE_LEVEL_MULT); 277 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);
279 start++; 279 start++;
280 } 280 }
281} 281}
@@ -287,18 +287,19 @@ static void walk_pmd_level(struct seq_file *m, struct pg_state *st, pud_t addr,
287{ 287{
288 int i; 288 int i;
289 pmd_t *start; 289 pmd_t *start;
290 pgprotval_t prot;
290 291
291 start = (pmd_t *) pud_page_vaddr(addr); 292 start = (pmd_t *) pud_page_vaddr(addr);
292 for (i = 0; i < PTRS_PER_PMD; i++) { 293 for (i = 0; i < PTRS_PER_PMD; i++) {
293 st->current_address = normalize_addr(P + i * PMD_LEVEL_MULT); 294 st->current_address = normalize_addr(P + i * PMD_LEVEL_MULT);
294 if (!pmd_none(*start)) { 295 if (!pmd_none(*start)) {
295 pgprotval_t prot = pmd_val(*start) & PTE_FLAGS_MASK; 296 if (pmd_large(*start) || !pmd_present(*start)) {
296 297 prot = pmd_flags(*start);
297 if (pmd_large(*start) || !pmd_present(*start))
298 note_page(m, st, __pgprot(prot), 3); 298 note_page(m, st, __pgprot(prot), 3);
299 else 299 } else {
300 walk_pte_level(m, st, *start, 300 walk_pte_level(m, st, *start,
301 P + i * PMD_LEVEL_MULT); 301 P + i * PMD_LEVEL_MULT);
302 }
302 } else 303 } else
303 note_page(m, st, __pgprot(0), 3); 304 note_page(m, st, __pgprot(0), 3);
304 start++; 305 start++;
@@ -318,19 +319,20 @@ static void walk_pud_level(struct seq_file *m, struct pg_state *st, pgd_t addr,
318{ 319{
319 int i; 320 int i;
320 pud_t *start; 321 pud_t *start;
322 pgprotval_t prot;
321 323
322 start = (pud_t *) pgd_page_vaddr(addr); 324 start = (pud_t *) pgd_page_vaddr(addr);
323 325
324 for (i = 0; i < PTRS_PER_PUD; i++) { 326 for (i = 0; i < PTRS_PER_PUD; i++) {
325 st->current_address = normalize_addr(P + i * PUD_LEVEL_MULT); 327 st->current_address = normalize_addr(P + i * PUD_LEVEL_MULT);
326 if (!pud_none(*start)) { 328 if (!pud_none(*start)) {
327 pgprotval_t prot = pud_val(*start) & PTE_FLAGS_MASK; 329 if (pud_large(*start) || !pud_present(*start)) {
328 330 prot = pud_flags(*start);
329 if (pud_large(*start) || !pud_present(*start))
330 note_page(m, st, __pgprot(prot), 2); 331 note_page(m, st, __pgprot(prot), 2);
331 else 332 } else {
332 walk_pmd_level(m, st, *start, 333 walk_pmd_level(m, st, *start,
333 P + i * PUD_LEVEL_MULT); 334 P + i * PUD_LEVEL_MULT);
335 }
334 } else 336 } else
335 note_page(m, st, __pgprot(0), 2); 337 note_page(m, st, __pgprot(0), 2);
336 338
@@ -351,6 +353,7 @@ void ptdump_walk_pgd_level(struct seq_file *m, pgd_t *pgd)
351#else 353#else
352 pgd_t *start = swapper_pg_dir; 354 pgd_t *start = swapper_pg_dir;
353#endif 355#endif
356 pgprotval_t prot;
354 int i; 357 int i;
355 struct pg_state st = {}; 358 struct pg_state st = {};
356 359
@@ -362,13 +365,13 @@ void ptdump_walk_pgd_level(struct seq_file *m, pgd_t *pgd)
362 for (i = 0; i < PTRS_PER_PGD; i++) { 365 for (i = 0; i < PTRS_PER_PGD; i++) {
363 st.current_address = normalize_addr(i * PGD_LEVEL_MULT); 366 st.current_address = normalize_addr(i * PGD_LEVEL_MULT);
364 if (!pgd_none(*start)) { 367 if (!pgd_none(*start)) {
365 pgprotval_t prot = pgd_val(*start) & PTE_FLAGS_MASK; 368 if (pgd_large(*start) || !pgd_present(*start)) {
366 369 prot = pgd_flags(*start);
367 if (pgd_large(*start) || !pgd_present(*start))
368 note_page(m, &st, __pgprot(prot), 1); 370 note_page(m, &st, __pgprot(prot), 1);
369 else 371 } else {
370 walk_pud_level(m, &st, *start, 372 walk_pud_level(m, &st, *start,
371 i * PGD_LEVEL_MULT); 373 i * PGD_LEVEL_MULT);
374 }
372 } else 375 } else
373 note_page(m, &st, __pgprot(0), 1); 376 note_page(m, &st, __pgprot(0), 1);
374 377