summaryrefslogtreecommitdiff
path: root/arch/arm/lib/semihosting.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/lib/semihosting.c')
-rw-r--r--arch/arm/lib/semihosting.c44
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;
}