target/riscv: Fix incorrect PTE merge in walk_pte

Two non-subsequent PTEs can be mapped to subsequent paddrs. In this
case, walk_pte will erroneously merge them.

Enforce the split up, by tracking the virtual base address.

Let's say we have the mapping:
0x81200000 -> 0x89623000 (4K)
0x8120f000 -> 0x89624000 (4K)

Before, walk_pte would have shown:

vaddr            paddr            size             attr
---------------- ---------------- ---------------- -------
0000000081200000 0000000089623000 0000000000002000 rwxu-ad

as it only checks for subsequent paddrs. With this patch, it becomes:

vaddr            paddr            size             attr
---------------- ---------------- ---------------- -------
0000000081200000 0000000089623000 0000000000001000 rwxu-ad
000000008120f000 0000000089624000 0000000000001000 rwxu-ad

Signed-off-by: Ralf Ramsauer <ralf.ramsauer@oth-regensburg.de>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-Id: <20220423215907.673663-1-ralf.ramsauer@oth-regensburg.de>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
Ralf Ramsauer 2022-04-23 23:59:07 +02:00 committed by Alistair Francis
parent cf7ed971ae
commit 457a86a0eb

View File

@ -84,6 +84,7 @@ static void walk_pte(Monitor *mon, hwaddr base, target_ulong start,
{ {
hwaddr pte_addr; hwaddr pte_addr;
hwaddr paddr; hwaddr paddr;
target_ulong last_start = -1;
target_ulong pgsize; target_ulong pgsize;
target_ulong pte; target_ulong pte;
int ptshift; int ptshift;
@ -111,12 +112,13 @@ static void walk_pte(Monitor *mon, hwaddr base, target_ulong start,
* A leaf PTE has been found * A leaf PTE has been found
* *
* If current PTE's permission bits differ from the last one, * If current PTE's permission bits differ from the last one,
* or current PTE's ppn does not make a contiguous physical * or the current PTE breaks up a contiguous virtual or
* address block together with the last one, print out the last * physical mapping, address block together with the last one,
* contiguous mapped block details. * print out the last contiguous mapped block details.
*/ */
if ((*last_attr != attr) || if ((*last_attr != attr) ||
(*last_paddr + *last_size != paddr)) { (*last_paddr + *last_size != paddr) ||
(last_start + *last_size != start)) {
print_pte(mon, va_bits, *vbase, *pbase, print_pte(mon, va_bits, *vbase, *pbase,
*last_paddr + *last_size - *pbase, *last_attr); *last_paddr + *last_size - *pbase, *last_attr);
@ -125,6 +127,7 @@ static void walk_pte(Monitor *mon, hwaddr base, target_ulong start,
*last_attr = attr; *last_attr = attr;
} }
last_start = start;
*last_paddr = paddr; *last_paddr = paddr;
*last_size = pgsize; *last_size = pgsize;
} else { } else {