]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
Merge patch series "arm64: add a software pagetable walker"
authorTom Rini <trini@konsulko.com>
Tue, 25 Jun 2024 23:22:36 +0000 (17:22 -0600)
committerTom Rini <trini@konsulko.com>
Wed, 26 Jun 2024 13:36:55 +0000 (07:36 -0600)
Caleb Connolly <caleb.connolly@linaro.org> says:

MMU issues are some of the most frustrating to debug. To make this
slightly less unbearable, introduce a software pagetable walker for
ARMv8. This can be called to dump a pagetable with the default
formatter, or a custom callback can be provided to implement more
complicated parsing.

This can also be useful to dump the pagetable used by a previous
bootloader stage (by reading out the ttbr register).

Here is an example of the output when walking U-Boot's own memory map
on a Qualcomm RB3 board:

Walking pagetable at 000000017df90000, va_bits: 36. Using 3 levels
[0x17df91000]                   |  Table |               |
  [0x17df92000]                 |  Table |               |
    [0x000001000 - 0x000200000] |  Pages | Device-nGnRnE | Non-shareable
  [0x000200000 - 0x040000000]   |  Block | Device-nGnRnE | Non-shareable
[0x040000000 - 0x080000000]     |  Block | Device-nGnRnE | Non-shareable
[0x080000000 - 0x140000000]     |  Block | Normal        | Inner-shareable
[0x17df93000]                   |  Table |               |
  [0x140000000 - 0x17de00000]   |  Block | Normal        | Inner-shareable
  [0x17df94000]                 |  Table |               |
    [0x17de00000 - 0x17dfa0000] |  Pages | Normal        | Inner-shareable

1  2 
arch/arm/include/asm/armv8/mmu.h

index ce655ce7a9525a02186e0ffd57a37d9e0bb26ca4,1348db4204ee4e1af02225188e34755a47b3347a..0ab681c893d3144168abdbd530decb3278ab0b59
@@@ -129,6 -129,62 +129,62 @@@ static inline void set_ttbr_tcr_mair(in
        asm volatile("isb");
  }
  
 - * pte_walker_cb_t - callback function for walk_pagetable.
+ static inline void get_ttbr_tcr_mair(int el, u64 *table, u64 *tcr, u64 *attr)
+ {
+       if (el == 1) {
+               asm volatile("mrs %0, ttbr0_el1" : "=r" (*table));
+               asm volatile("mrs %0, tcr_el1" : "=r" (*tcr));
+               asm volatile("mrs %0, mair_el1" : "=r" (*attr));
+       } else if (el == 2) {
+               asm volatile("mrs %0, ttbr0_el2" : "=r" (*table));
+               asm volatile("mrs %0, tcr_el2" : "=r" (*tcr));
+               asm volatile("mrs %0, mair_el2" : "=r" (*attr));
+       } else if (el == 3) {
+               asm volatile("mrs %0, ttbr0_el3" : "=r" (*table));
+               asm volatile("mrs %0, tcr_el3" : "=r" (*tcr));
+               asm volatile("mrs %0, mair_el3" : "=r" (*attr));
+       } else {
+               hang();
+       }
+ }
+ /**
++ * typedef pte_walker_cb_t - callback function for walk_pagetable.
+  *
+  * This function is called when the walker finds a table entry
+  * or after parsing a block or pages. For a table the @end address
+  * is 0, and @addr is the address of the table. Otherwise, they
+  * are the start and end physical addresses of the block or page.
+  *
+  * @addr: PTE start address (PA), or address of table. Includes attributes.
+  * @end: End address of the region (or 0 for a table)
+  * @va_bits: Number of bits in the virtual address
+  * @level: Table level
+  * @priv: Private data for the callback
+  *
+  * Return: true to stop walking, false to continue
+  */
+ typedef bool (*pte_walker_cb_t)(u64 addr, u64 end, int va_bits, int level, void *priv);
+ /**
+  * walk_pagetable() - Walk the pagetable at ttbr and call @cb for each region
+  *
+  * @ttbr: Address of the pagetable to dump
+  * @tcr: TCR value to use
+  * @cb: Callback function to call for each entry
+  * @priv: Private data for the callback
+  */
+ void walk_pagetable(u64 ttbr, u64 tcr, pte_walker_cb_t cb, void *priv);
+ /**
+  * dump_pagetable() - Dump the pagetable at ttbr, printing each region and
+  * level.
+  *
+  * @ttbr: Address of the pagetable to dump
+  * @tcr: TCR value to use
+  */
+ void dump_pagetable(u64 ttbr, u64 tcr);
  struct mm_region {
        u64 virt;
        u64 phys;