diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/lib/semihosting.c | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/arch/arm/lib/semihosting.c b/arch/arm/lib/semihosting.c index acc6b1be4f..3dee7d51b3 100644 --- a/arch/arm/lib/semihosting.c +++ b/arch/arm/lib/semihosting.c @@ -20,6 +20,12 @@ #define SYSFLEN 0x0C #define SYSERRNO 0x13 +/* + * Macro to force the compiler to *populate* memory (for an array or struct) + * before passing the pointer to an inline assembly call. + */ +#define USE_PTR(ptr) *(const char (*)[]) (ptr) + #if defined(CONFIG_ARM64) #define SMH_TRAP "hlt #0xf000" #elif defined(CONFIG_CPU_V7M) @@ -37,9 +43,17 @@ static noinline long smh_trap(unsigned int sysnum, void *addr) { register long result asm("r0"); + /* + * We need a memory clobber (aka compiler barrier) for two reasons: + * - The compiler needs to populate any data structures pointed to + * by "addr" *before* the trap instruction is called. + * - At least the SYSREAD function puts the result into memory pointed + * to by "addr", so the compiler must not use a cached version of + * the previous content, after the call has finished. + */ asm volatile (SMH_TRAP : "=r" (result) - : "0"(sysnum), "r"(addr) + : "0"(sysnum), "r"(USE_PTR(addr)) : "memory"); return result; |