Self-Modifying Code - 2024.2 English

MicroBlaze Processor Reference Guide (UG984)

Document ID
UG984
Release Date
2024-11-27
Version
2024.2 English

When using self-modifying code software must ensure that the modified instructions have been written to memory prior to fetching them for execution. There are several aspects to consider:

  • The instructions to be modified could already have been fetched prior to modification:
    • Into the instruction prefetch buffer
    • Into the instruction cache, if it is enabled
    • Into a stream buffer, if instruction cache stream buffers are used
    • Into the instruction cache, and then saved in a victim buffer, if victim buffers are used.
    To ensure that the modified code is always executed instead of the old unmodified code, software must handle all these cases.
  • If one or more of the instructions to be modified is a branch, and the branch target cache is used, the branch target address might have been cached.

    To avoid using the cached branch target address, software must ensure that the branch target cache is cleared prior to executing the modified code.

  • The modified instructions might not have been written to memory prior to execution:
    • They might be en-route to memory, in temporary storage in the interconnect or the memory controller.
    • They might be stored in the data cache, if write-back cache is used.
    • They might be saved in a victim buffer, if write-back cache and victim buffers are used.

Software must ensure that the modified instructions have been written to memory before being fetched by the processor.

The annotated code below shows how each of the above issues can be addressed. This code assumes that both instruction cache and write-back data cache is used. If not, the corresponding instructions can be omitted.

The following code exemplifies storing a modified instruction:

swi         r5,r6,0  ; r5 = new instruction
                     ; r6 = physical instruction address
wdc.flush   r6,r0    ; flush write-back data cache line
mbar        1        ; ensure new instruction is written to memory
wic         r7,r0    ; invalidate line, empty stream & victim buffers
                     ; r7 = virtual instruction address
mbar        2        ; empty prefetch buffer, clear branch target cache

The physical and virtual addresses above are identical, unless MMU virtual mode is used. If the MMU is enabled, the code sequences must be executed in real mode, because WIC and WDC are privileged instructions. The first instruction after the code sequences above must not be modified, because it might have been prefetched.