Skip to content

Commit

Permalink
powerpc/mm: Add physical address to Linux page table dump
Browse files Browse the repository at this point in the history
The current page table dumper scans the Linux page tables and coalesces mappings
with adjacent virtual addresses and similar PTE flags. This behaviour is
somewhat broken when you consider the IOREMAP space where entirely unrelated
mappings will appear to be virtually contiguous. This patch modifies the range
coalescing so that only ranges that are both physically and virtually contiguous
are combined. This patch also adds to the dump output the physical address at
the start of each range.

Fixes: 8eb07b1 ("powerpc/mm: Dump linux pagetables")
Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
[mpe: Print the physicall address with 0x like the other addresses]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
  • Loading branch information
Oliver O'Halloran authored and Michael Ellerman committed Apr 12, 2017
1 parent 70538ea commit aaa2295
Showing 1 changed file with 16 additions and 2 deletions.
18 changes: 16 additions & 2 deletions arch/powerpc/mm/dump_linuxpagetables.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ struct pg_state {
struct seq_file *seq;
const struct addr_marker *marker;
unsigned long start_address;
unsigned long start_pa;
unsigned long last_pa;
unsigned int level;
u64 current_flags;
};
Expand Down Expand Up @@ -265,7 +267,9 @@ static void dump_addr(struct pg_state *st, unsigned long addr)
const char *unit = units;
unsigned long delta;

seq_printf(st->seq, "0x%016lx-0x%016lx ", st->start_address, addr-1);
seq_printf(st->seq, "0x%016lx-0x%016lx ", st->start_address, addr-1);
seq_printf(st->seq, "0x%016lx ", st->start_pa);

delta = (addr - st->start_address) >> 10;
/* Work out what appropriate unit to use */
while (!(delta & 1023) && unit[1]) {
Expand All @@ -280,21 +284,27 @@ static void note_page(struct pg_state *st, unsigned long addr,
unsigned int level, u64 val)
{
u64 flag = val & pg_level[level].mask;
u64 pa = val & PTE_RPN_MASK;

/* At first no level is set */
if (!st->level) {
st->level = level;
st->current_flags = flag;
st->start_address = addr;
st->start_pa = pa;
st->last_pa = pa;
seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
/*
* Dump the section of virtual memory when:
* - the PTE flags from one entry to the next differs.
* - we change levels in the tree.
* - the address is in a different section of memory and is thus
* used for a different purpose, regardless of the flags.
* - the pa of this page is not adjacent to the last inspected page
*/
} else if (flag != st->current_flags || level != st->level ||
addr >= st->marker[1].start_address) {
addr >= st->marker[1].start_address ||
pa != st->last_pa + PAGE_SIZE) {

/* Check the PTE flags */
if (st->current_flags) {
Expand All @@ -318,8 +328,12 @@ static void note_page(struct pg_state *st, unsigned long addr,
seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
}
st->start_address = addr;
st->start_pa = pa;
st->last_pa = pa;
st->current_flags = flag;
st->level = level;
} else {
st->last_pa = pa;
}
}

Expand Down

0 comments on commit aaa2295

Please sign in to comment.