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

```asm
; 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
```
Parents
  • why memory barrier is needed?

    I think this is section of the Arm ARM you need:

    B2.10.1 Instruction Synchronization Barrier (ISB)
    An ISB instruction ensures that all instructions that come after the ISB instruction in program order are fetched from
    the cache or memory after the ISB instruction has completed. Using an ISB ensures that the effects of
    context-changing operations executed before the ISB are visible to the instructions fetched after the ISB instruction.
    Examples of context-changing operations that require the insertion of an ISB instruction to ensure the effects of the
    operation are visible to instructions fetched after the ISB instruction are:

    • Completed cache and TLB maintenance instructions.
    • Changes to System registers

    A change to a TTBR is a change to the PE's context.  A change to context is only guaranteed to be visible after a context synchronization event , which is either an ISB or exception entry/exit (note: see FEAT_ExS).  Meaning in your case, without the ISB the PE might still be using the "old" context at the time of TLBI.  Leading it to attempt to re-walk the tables using the old configuration.

    if yes, why can't use `dsb` replaced?

    Because ISBs and DSBs do different things.  Sometimes you need one, sometimes the other, sometimes a combination - it all depends on what you are trying to achieve.  If you had one "super" barrier that did everything that would end up being inefficient as often you'd be over ordering.

            msr  ttbr1_el1, \tmp2
            isb  <-- ensure change in context (write to TTBR) is visible to following instructions
            tlbi vmalle1
            dsb  nsh <-- ensure TLBI completes before processing next instruction
            isb <-- ensure instructions beyond this point are fetched using the post-TBLI translations
Reply
  • why memory barrier is needed?

    I think this is section of the Arm ARM you need:

    B2.10.1 Instruction Synchronization Barrier (ISB)
    An ISB instruction ensures that all instructions that come after the ISB instruction in program order are fetched from
    the cache or memory after the ISB instruction has completed. Using an ISB ensures that the effects of
    context-changing operations executed before the ISB are visible to the instructions fetched after the ISB instruction.
    Examples of context-changing operations that require the insertion of an ISB instruction to ensure the effects of the
    operation are visible to instructions fetched after the ISB instruction are:

    • Completed cache and TLB maintenance instructions.
    • Changes to System registers

    A change to a TTBR is a change to the PE's context.  A change to context is only guaranteed to be visible after a context synchronization event , which is either an ISB or exception entry/exit (note: see FEAT_ExS).  Meaning in your case, without the ISB the PE might still be using the "old" context at the time of TLBI.  Leading it to attempt to re-walk the tables using the old configuration.

    if yes, why can't use `dsb` replaced?

    Because ISBs and DSBs do different things.  Sometimes you need one, sometimes the other, sometimes a combination - it all depends on what you are trying to achieve.  If you had one "super" barrier that did everything that would end up being inefficient as often you'd be over ordering.

            msr  ttbr1_el1, \tmp2
            isb  <-- ensure change in context (write to TTBR) is visible to following instructions
            tlbi vmalle1
            dsb  nsh <-- ensure TLBI completes before processing next instruction
            isb <-- ensure instructions beyond this point are fetched using the post-TBLI translations
Children