arm: smh: Add option to detect semihosting
authorSean Anderson <sean.anderson@seco.com>
Tue, 22 Mar 2022 20:59:30 +0000 (16:59 -0400)
committerTom Rini <trini@konsulko.com>
Fri, 1 Apr 2022 20:56:53 +0000 (16:56 -0400)
These functions are intended to support detecting semihosting and
falling back gracefully to alternative implementations. The test starts
by making semihosting call. SYS_ERRNO is chosen because it should not
mutate any state. If this semihosting call results in an exception
(rather than being caught by the debugger), then the exception handler
should call disable_semihosting() and resume execution after the call.

Ideally, this would just be part of semihosting by default, and not a
separate config. However, to reduce space ARM SPL doesn't include
exception vectors by default. This means we can't detect if a
semihosting call failed unless we enable them. To avoid forcing them to
be enabled, we use a separate config option. It might also be possible
to try and detect whether a debugger has enabled (by reading HDE from
DSCR), but I wasn't able to figure out a way to do this from all ELs.

This patch just introduces the generic code to handle detection. The
next patch will implement it for arm64 (but not arm32).

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
arch/arm/Kconfig
arch/arm/lib/semihosting.c
include/semihosting.h

index b2e2873448fd5112209af7d10c308808f3a7b260..f277929c991853d9545a29846bb9d9ae3b5345c9 100644 (file)
@@ -414,6 +414,16 @@ config SEMIHOSTING
          on the host system. If you don't have a debugger attached then trying
          to do this will likely cause U-Boot to hang. Say 'n' if you are unsure.
 
+config SEMIHOSTING_FALLBACK
+       bool "Recover gracefully when semihosting fails"
+       depends on SEMIHOSTING && ARM64
+       default y
+       help
+         Normally, if U-Boot makes a semihosting call and no debugger is
+         attached, then it will panic due to a synchronous abort
+         exception. This config adds an exception handler which will allow
+         U-Boot to recover. Say 'y' if unsure.
+
 config SPL_SEMIHOSTING
        bool "Support ARM semihosting in SPL"
        depends on SPL
@@ -427,6 +437,17 @@ config SPL_SEMIHOSTING
          on the host system. If you don't have a debugger attached then trying
          to do this will likely cause U-Boot to hang. Say 'n' if you are unsure.
 
+config SPL_SEMIHOSTING_FALLBACK
+       bool "Recover gracefully when semihosting fails in SPL"
+       depends on SPL_SEMIHOSTING && ARM64
+       select ARMV8_SPL_EXCEPTION_VECTORS
+       default y
+       help
+         Normally, if U-Boot makes a semihosting call and no debugger is
+         attached, then it will panic due to a synchronous abort
+         exception. This config adds an exception handler which will allow
+         U-Boot to recover. Say 'y' if unsure.
+
 config SYS_THUMB_BUILD
        bool "Build U-Boot using the Thumb instruction set"
        depends on !ARM64
index 7595dbc4a93d11f222db33d93f42fc70fbc69d00..dbea2b06fb27271579f2dc0f1ddd7291f0d65474 100644 (file)
@@ -20,6 +20,7 @@
 #define SYSWRITE       0x05
 #define SYSREAD                0x06
 #define SYSREADC       0x07
+#define SYSISERROR     0x08
 #define SYSSEEK                0x0A
 #define SYSFLEN                0x0C
 #define SYSERRNO       0x13
@@ -41,6 +42,26 @@ static noinline long smh_trap(unsigned int sysnum, void *addr)
        return result;
 }
 
+#if CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK)
+static bool _semihosting_enabled = true;
+static bool try_semihosting = true;
+
+bool semihosting_enabled(void)
+{
+       if (try_semihosting) {
+               smh_trap(SYSERRNO, NULL);
+               try_semihosting = false;
+       }
+
+       return _semihosting_enabled;
+}
+
+void disable_semihosting(void)
+{
+       _semihosting_enabled = false;
+}
+#endif
+
 /**
  * smh_errno() - Read the host's errno
  *
index 6f3c29786cef724148a8a0b63e2ec5266fc36680..9816233c508dcfec6b010582ee60ac81c090c197 100644 (file)
@@ -6,6 +6,36 @@
 #ifndef _SEMIHOSTING_H
 #define _SEMIHOSTING_H
 
+#if CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK)
+/**
+ * semihosting_enabled() - Determine whether semihosting is supported
+ *
+ * Semihosting-based drivers should call this function before making other
+ * semihosting calls.
+ *
+ * Return: %true if a debugger is attached which supports semihosting, %false
+ *         otherwise
+ */
+bool semihosting_enabled(void);
+
+/**
+ * disable_semihosting() - Cause semihosting_enabled() to return false
+ *
+ * If U-Boot ever receives an unhandled exception caused by a semihosting trap,
+ * the trap handler should call this function.
+ */
+void disable_semihosting(void);
+#else
+static inline bool semihosting_enabled(void)
+{
+       return CONFIG_IS_ENABLED(SEMIHOSTING);
+}
+
+static inline void disable_semihosting(void)
+{
+}
+#endif
+
 /**
  * enum smh_open_mode - Numeric file modes for use with smh_open()
  * MODE_READ: 'r'