Reputation: 105
I encountered a problem about replacing the active TTBR0_EL2 register. It seems that the new data loading does not use the new page table, or the instruction execution is messed up. In short, Data Abort is triggered, and ISS indicates that the error details are at translation level 1.
I compared the process of modifying the page table base address in the Linux kernel and found that the Linux kernel added an isb
instruction between modifying ttbr and TLB refresh. So I added it and found that everything worked fine.
I read the ARM manual and some online information, but I didn't figure out why.
dsb
replaced?Configuration: MMU on, dcache off, icache off
; linux/arch/arm64/mm/proc.S
.macro __idmap_cpu_set_reserved_ttbr1, tmp1, tmp2
adrp \tmp1, reserved_pg_dir
phys_to_ttbr \tmp2, \tmp1
offset_ttbr1 \tmp2, \tmp1
msr ttbr1_el1, \tmp2
isb
tlbi vmalle1
dsb nsh
isb
.endm
Upvotes: 2
Views: 70
Reputation: 1
msr writes a system register, which in general doesn't count as a memory write, so normally memory synchronisation instructions like dmb and dsb won't work for them. If you want to be sure that later instructions aren't re-ordered to before the mrs, you need an isb.
(To prevent previous memory accesses to be re-ordered after the mrs, in general I would have expected a dsb before the mrs, but perhaps that's not needed for ttbr1_el1?)
Without the isb, tlbi could execute before the mrs is finished and act on the wrong TLB entries.
The dsb is needed to prevent memory accesses after the tlbi instruction to be executed too early, before the tlbi. Assuming the tlbi is needed (which I think isn't in general after changing ttbr1_el1), without the dsb those memory accesses could use stale TLB translations that haven't been flushed by the tlbi yet.
The last isb is needed to make sure that the following instruction see the effects for the previous ones. I think that's only needed if the following instructions need to be refetched with the new TLB settings too. So the dsb is to sync later memory accesses, while the isb syncs future instructions.
Reasonably well explained here: https://developer.arm.com/documentation/100941/0101/Barriers
Upvotes: 0