diff options
| author | Damien George <damien@micropython.org> | 2021-06-04 01:17:09 +1000 |
|---|---|---|
| committer | Damien George <damien@micropython.org> | 2021-06-05 11:03:04 +1000 |
| commit | a70a4e6688c6b29797b1e314ce2841e8e4fecb7b (patch) | |
| tree | e80ecb4c5ded463235da813735ac2a75ec0f324e /py/emitglue.c | |
| parent | fad0efdcf277dcc5698d59445074f4ee806d7976 (diff) | |
py/emitglue: Always flush caches when assigning native ARM code.
Prior to this commit, cache flushing for ARM native code was done only in
the assembler code asm_thumb_end_pass()/asm_arm_end_pass(), at the last
pass of the assembler. But this misses flushing the cache when loading
native code from an .mpy file, ie in persistentcode.c.
The change here makes sure the cache is always flushed/cleaned/invalidated
when assigning native code on ARM architectures.
This problem was found running tests/micropython/import_mpy_native_gc.py on
the mimxrt port.
Signed-off-by: Damien George <damien@micropython.org>
Diffstat (limited to 'py/emitglue.c')
| -rw-r--r-- | py/emitglue.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/py/emitglue.c b/py/emitglue.c index 0ef708a3f..09b48682f 100644 --- a/py/emitglue.c +++ b/py/emitglue.c @@ -108,6 +108,31 @@ void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void assert(kind == MP_CODE_NATIVE_PY || kind == MP_CODE_NATIVE_VIPER || kind == MP_CODE_NATIVE_ASM); + // Some architectures require flushing/invalidation of the I/D caches, + // so that the generated native code which was created in data RAM will + // be available for execution from instruction RAM. + #if MICROPY_EMIT_THUMB || MICROPY_EMIT_INLINE_THUMB + #if __ICACHE_PRESENT == 1 + // Flush D-cache, so the code emitted is stored in RAM. + MP_HAL_CLEAN_DCACHE(fun_data, fun_len); + // Invalidate I-cache, so the newly-created code is reloaded from RAM. + SCB_InvalidateICache(); + #endif + #elif MICROPY_EMIT_ARM + #if (defined(__linux__) && defined(__GNUC__)) || __ARM_ARCH == 7 + __builtin___clear_cache(fun_data, (uint8_t *)fun_data + fun_len); + #elif defined(__arm__) + // Flush I-cache and D-cache. + asm volatile ( + "0:" + "mrc p15, 0, r15, c7, c10, 3\n" // test and clean D-cache + "bne 0b\n" + "mov r0, #0\n" + "mcr p15, 0, r0, c7, c7, 0\n" // invalidate I-cache and D-cache + : : : "r0", "cc"); + #endif + #endif + rc->kind = kind; rc->scope_flags = scope_flags; rc->n_pos_args = n_pos_args; |
