wangloo
wangloo

Reputation: 105

Is the isb necessary between modifying ttbr and flushing TLB?

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.

  1. why memory barrier is needed?
  2. if yes, why can't use 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

Answers (1)

Indan
Indan

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

Related Questions