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>
This commit is contained in:
parent
fad0efdcf2
commit
a70a4e6688
19
py/asmarm.c
19
py/asmarm.c
|
@ -38,25 +38,6 @@
|
||||||
|
|
||||||
#define SIGNED_FIT24(x) (((x) & 0xff800000) == 0) || (((x) & 0xff000000) == 0xff000000)
|
#define SIGNED_FIT24(x) (((x) & 0xff800000) == 0) || (((x) & 0xff000000) == 0xff000000)
|
||||||
|
|
||||||
void asm_arm_end_pass(asm_arm_t *as) {
|
|
||||||
if (as->base.pass == MP_ASM_PASS_EMIT) {
|
|
||||||
#if (defined(__linux__) && defined(__GNUC__)) || __ARM_ARCH == 7
|
|
||||||
char *start = mp_asm_base_get_code(&as->base);
|
|
||||||
char *end = start + mp_asm_base_get_code_size(&as->base);
|
|
||||||
__builtin___clear_cache(start, end);
|
|
||||||
#elif defined(__arm__)
|
|
||||||
// flush I- 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert word into instruction flow
|
// Insert word into instruction flow
|
||||||
STATIC void emit(asm_arm_t *as, uint op) {
|
STATIC void emit(asm_arm_t *as, uint op) {
|
||||||
uint8_t *c = mp_asm_base_get_cur_to_write_bytes(&as->base, 4);
|
uint8_t *c = mp_asm_base_get_cur_to_write_bytes(&as->base, 4);
|
||||||
|
|
|
@ -72,7 +72,9 @@ typedef struct _asm_arm_t {
|
||||||
uint stack_adjust;
|
uint stack_adjust;
|
||||||
} asm_arm_t;
|
} asm_arm_t;
|
||||||
|
|
||||||
void asm_arm_end_pass(asm_arm_t *as);
|
static inline void asm_arm_end_pass(asm_arm_t *as) {
|
||||||
|
(void)as;
|
||||||
|
}
|
||||||
|
|
||||||
void asm_arm_entry(asm_arm_t *as, int num_locals);
|
void asm_arm_entry(asm_arm_t *as, int num_locals);
|
||||||
void asm_arm_exit(asm_arm_t *as);
|
void asm_arm_exit(asm_arm_t *as);
|
||||||
|
|
|
@ -35,7 +35,6 @@
|
||||||
|
|
||||||
#include "py/mpstate.h"
|
#include "py/mpstate.h"
|
||||||
#include "py/persistentcode.h"
|
#include "py/persistentcode.h"
|
||||||
#include "py/mphal.h"
|
|
||||||
#include "py/asmthumb.h"
|
#include "py/asmthumb.h"
|
||||||
|
|
||||||
#define UNSIGNED_FIT5(x) ((uint32_t)(x) < 32)
|
#define UNSIGNED_FIT5(x) ((uint32_t)(x) < 32)
|
||||||
|
@ -62,20 +61,6 @@ static inline byte *asm_thumb_get_cur_to_write_bytes(asm_thumb_t *as, int n) {
|
||||||
return mp_asm_base_get_cur_to_write_bytes(&as->base, n);
|
return mp_asm_base_get_cur_to_write_bytes(&as->base, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
void asm_thumb_end_pass(asm_thumb_t *as) {
|
|
||||||
(void)as;
|
|
||||||
// could check labels are resolved...
|
|
||||||
|
|
||||||
#if __ICACHE_PRESENT == 1
|
|
||||||
if (as->base.pass == MP_ASM_PASS_EMIT) {
|
|
||||||
// flush D-cache, so the code emitted is stored in memory
|
|
||||||
MP_HAL_CLEAN_DCACHE(as->base.code_base, as->base.code_size);
|
|
||||||
// invalidate I-cache
|
|
||||||
SCB_InvalidateICache();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
STATIC void asm_thumb_write_byte_1(asm_thumb_t *as, byte b1) {
|
STATIC void asm_thumb_write_byte_1(asm_thumb_t *as, byte b1) {
|
||||||
byte *c = asm_thumb_get_cur_to_write_bytes(as, 1);
|
byte *c = asm_thumb_get_cur_to_write_bytes(as, 1);
|
||||||
|
|
|
@ -70,7 +70,9 @@ typedef struct _asm_thumb_t {
|
||||||
uint32_t stack_adjust;
|
uint32_t stack_adjust;
|
||||||
} asm_thumb_t;
|
} asm_thumb_t;
|
||||||
|
|
||||||
void asm_thumb_end_pass(asm_thumb_t *as);
|
static inline void asm_thumb_end_pass(asm_thumb_t *as) {
|
||||||
|
(void)as;
|
||||||
|
}
|
||||||
|
|
||||||
void asm_thumb_entry(asm_thumb_t *as, int num_locals);
|
void asm_thumb_entry(asm_thumb_t *as, int num_locals);
|
||||||
void asm_thumb_exit(asm_thumb_t *as);
|
void asm_thumb_exit(asm_thumb_t *as);
|
||||||
|
|
|
@ -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);
|
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->kind = kind;
|
||||||
rc->scope_flags = scope_flags;
|
rc->scope_flags = scope_flags;
|
||||||
rc->n_pos_args = n_pos_args;
|
rc->n_pos_args = n_pos_args;
|
||||||
|
|
Loading…
Reference in New Issue