
On Wed, 08 Jan 2025 15:19:07 +0000, Caleb Connolly caleb.connolly@linaro.org wrote:
Hi Marc,
Thanks for your comments.
On 08/01/2025 16:05, Marc Zyngier wrote:
On Wed, 08 Jan 2025 14:22:24 +0000, Caleb Connolly caleb.connolly@linaro.org wrote:
This seems to cause crashes on a bunch of Qualcomm platforms. It's safer to just update the live table and flush it.
You may want to provide a bit more information, because that's not much to go on, really.
Best I have is "the board hangs and then resets when trying to switch pagetables", I didn't manage to narrow it down exactly, but since it seems to work to update the tables without switching that feels like a better approach at least for now.
I think you should completely characterise the issue before changing things like this. My hunch is that the so-called "emergency" page tables do not map the page tables you're modifying. Or something along those lines. But you really want to get to the bottom of it.
In hindsight, this mmu_map_region() function is not great in a lot of ways, I'm still getting my head around the MMU and I expect this will keep being improved.
Signed-off-by: Caleb Connolly caleb.connolly@linaro.org
arch/arm/cpu/armv8/cache_v8.c | 11 ++--------- arch/arm/include/asm/system.h | 3 +-- drivers/soc/qcom/cmd-db.c | 2 +- 3 files changed, 4 insertions(+), 12 deletions(-)
diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c index e6be6359c5d9..43051d156122 100644 --- a/arch/arm/cpu/armv8/cache_v8.c +++ b/arch/arm/cpu/armv8/cache_v8.c @@ -338,9 +338,9 @@ static void map_range(u64 virt, u64 phys, u64 size, int level, size -= next_size; } }
-void mmu_map_region(phys_addr_t addr, u64 size, bool emergency) +void mmu_map_region(phys_addr_t addr, u64 size) { u64 va_bits; int level = 0; u64 attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_INNER_SHARE; @@ -350,19 +350,12 @@ void mmu_map_region(phys_addr_t addr, u64 size, bool emergency) get_tcr(NULL, &va_bits); if (va_bits < 39) level = 1;
if (emergency)
map_range(addr, addr, size, level,
(u64 *)gd->arch.tlb_emerg, attrs);
/* Switch pagetables while we update the primary one */
__asm_switch_ttbr(gd->arch.tlb_emerg);
map_range(addr, addr, size, level, (u64 *)gd->arch.tlb_addr, attrs);
__asm_switch_ttbr(gd->arch.tlb_addr);
- flush_dcache_range(gd->arch.tlb_addr, gd->arch.tlb_size);
Why would you invalidate anything when *mapping* something? By definition, if there was nothing mapped before, there is nothing to invalidate (hint: the architecture forbids negative caching).
This isn't flushing the region or TLB, it's flushing the translation table we just modified.
Ah, you're obviously right. I can't read today...
But it then begs the question: are the page tables configured to be accessed by the page-table walker in a non-cacheable fashion? That'd be rather silly, and the only reason why you'd need any form of CMO at this point.
I'm wondering if this tlb_addr variable is misnamed, I'm reading ARM docs which suggest the TLB is some cache inside(?) the MMU, but this tlb_addr in U-Boot actually points to the translation table in memory if my understanding is correct?
That's my impression, but each time I look at this code, I feel a bit sick...
M.