diff options
Diffstat (limited to 'arch/arm/lib/semihosting.c')
-rw-r--r-- | arch/arm/lib/semihosting.c | 44 |
1 files changed, 31 insertions, 13 deletions
diff --git a/arch/arm/lib/semihosting.c b/arch/arm/lib/semihosting.c index 01d652a6b83..939c0f75132 100644 --- a/arch/arm/lib/semihosting.c +++ b/arch/arm/lib/semihosting.c @@ -4,11 +4,6 @@ * Copyright 2014 Broadcom Corporation */ -/* - * This code has been tested on arm64/aarch64 fastmodel only. An untested - * placeholder exists for armv7 architectures, but since they are commonly - * available in silicon now, fastmodel usage makes less sense for them. - */ #include <common.h> #include <log.h> #include <semihosting.h> @@ -26,19 +21,42 @@ #define SYSERRNO 0x13 /* - * Call the handler + * Macro to force the compiler to *populate* memory (for an array or struct) + * before passing the pointer to an inline assembly call. */ -static noinline long smh_trap(unsigned int sysnum, void *addr) -{ - register long result asm("r0"); +#define USE_PTR(ptr) *(const char (*)[]) (ptr) + #if defined(CONFIG_ARM64) - asm volatile ("hlt #0xf000" : "=r" (result) : "0"(sysnum), "r"(addr) : "memory"); + #define SMH_TRAP "hlt #0xf000" #elif defined(CONFIG_CPU_V7M) - asm volatile ("bkpt #0xAB" : "=r" (result) : "0"(sysnum), "r"(addr) : "memory"); + #define SMH_TRAP "bkpt #0xAB" +#elif defined(CONFIG_SYS_THUMB_BUILD) + #define SMH_TRAP "svc #0xab" #else - /* Note - untested placeholder */ - asm volatile ("svc #0x123456" : "=r" (result) : "0"(sysnum), "r"(addr) : "memory"); + #define SMH_TRAP "svc #0x123456" #endif + +/* + * Call the handler + */ +static long smh_trap(unsigned int sysnum, void *addr) +{ + register long result asm("r0"); + register void *_addr asm("r1") = addr; + + /* + * 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"(USE_PTR(_addr)) + : "memory"); + return result; } |