This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][Newlib][libgloss][AArch64] - Semihosting v2 AArch64 implementation (5 / 5)


Hi All, 


This patch adds support for Semihosting v2 support for ARM
in libgloss.

Semihosting v2 changes are documented here:
https://developer.arm.com/docs/100863/latest/

The biggest change is the addition of an extensions mechanism
to add more extensions in the future.

Regression tested on aarch64-none-elf and no regressions.

OK for master?

PS. I don't have commmit rights so if OK can someone apply for me?

Thanks,
Tamar


libgloss/aarch64/
2017-07-03  Tamar Christina  <tamar.christina@arm.com>

	* _kill.c (_kill): Add exit code reporting.
	* _exit.c (_exit): Likewise.
	* svc.h (AngelSVC_Reason_IsError): New.
	(AngelSVC_Reason_ReportExceptionExtended): New.
	(AngelSVC_Reason_Elapsed, AngelSVC_Reason_TickFreq): New.
	(NUM_SHFB_MAGIC, SHFB_MAGIC_0, SHFB_MAGIC_2, SHFB_MAGIC_3): New.
	(SH_EXT_EXIT_EXTENDED_BITNUM, SH_EXT_STDOUT_STDERR_BITNUM): New.
	* syscalls.c (get_semihosting_exts, has_ext_exit_extended): New.
	(has_ext_stdout_stderr, initialise_semihosting_exts): New.
	(initialise_monitor_handles): Check for extension.
diff --git a/libgloss/aarch64/_exit.c b/libgloss/aarch64/_exit.c
index a4f9d9eb5e474a43ef669688eb9b4d80d1ad3a0c..1a6b01532d24204172d36d5bbbfcf52c40863805 100644
--- a/libgloss/aarch64/_exit.c
+++ b/libgloss/aarch64/_exit.c
@@ -36,6 +36,12 @@ _exit (int status)
       param_block_t block[2];
       block[0] = ADP_Stopped_ApplicationExit;
       block[1] = status;
-      do_AngelSVC (AngelSVC_Reason_ReportException, block);
+
+#if SEMIHOST_V2
+      if (_has_ext_exit_extended ())
+	 do_AngelSVC (AngelSVC_Reason_ReportExceptionExtended, block);
+      else
+#endif
+	 do_AngelSVC (AngelSVC_Reason_ReportException, block);
     }
 }
diff --git a/libgloss/aarch64/_kill.c b/libgloss/aarch64/_kill.c
index af33f07b075d055dc4170fd8180b52e6b3c46142..1d42371f0a29037e67757065490c0facbcccdf28 100644
--- a/libgloss/aarch64/_kill.c
+++ b/libgloss/aarch64/_kill.c
@@ -45,5 +45,11 @@ _kill (int pid, int sig)
 
   block[0] = ADP_Stopped_RunTimeError;
   block[1] = sig;
-  return do_AngelSVC (AngelSVC_Reason_ReportException, block);
+
+#if SEMIHOST_V2
+  if (_has_ext_exit_extended ())
+    return do_AngelSVC (AngelSVC_Reason_ReportExceptionExtended, block);
+  else
+#endif
+    return do_AngelSVC (AngelSVC_Reason_ReportException, block);
 }
diff --git a/libgloss/aarch64/svc.h b/libgloss/aarch64/svc.h
index fe249f08a413de6b01945a8f45b65aa74f4782d9..60bd00fcacbfc3bd75ef3735eb6867a2718048d5 100644
--- a/libgloss/aarch64/svc.h
+++ b/libgloss/aarch64/svc.h
@@ -23,37 +23,59 @@
  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
 
+#include <_ansi.h>
+
 /* Now the SWI numbers and reason codes for RDI (Angel) monitors.  */
-#define AngelSVC			0xF000
-#define AngelSVCInsn			"hlt"
-#define AngelSVCAsm			hlt
+#define AngelSVC				0xF000
+#define AngelSVCInsn				"hlt"
+#define AngelSVCAsm				hlt
 
 /* The reason codes:  */
-#define AngelSVC_Reason_Open		0x01
-#define AngelSVC_Reason_Close		0x02
-#define AngelSVC_Reason_WriteC		0x03
-#define AngelSVC_Reason_Write0		0x04
-#define AngelSVC_Reason_Write		0x05
-#define AngelSVC_Reason_Read		0x06
-#define AngelSVC_Reason_ReadC		0x07
-#define AngelSVC_Reason_IsTTY		0x09
-#define AngelSVC_Reason_Seek		0x0A
-#define AngelSVC_Reason_FLen		0x0C
-#define AngelSVC_Reason_TmpNam		0x0D
-#define AngelSVC_Reason_Remove		0x0E
-#define AngelSVC_Reason_Rename		0x0F
-#define AngelSVC_Reason_Clock		0x10
-#define AngelSVC_Reason_Time		0x11
-#define AngelSVC_Reason_System		0x12
-#define AngelSVC_Reason_Errno		0x13
-#define AngelSVC_Reason_GetCmdLine	0x15
-#define AngelSVC_Reason_HeapInfo	0x16
-#define AngelSVC_Reason_EnterSVC	0x17
-#define AngelSVC_Reason_ReportException 0x18
-#define AngelSVC_Reason_SyncCacheRange	0x19
-#define AngelSVC_Reason_Elapsed         0x30
-#define ADP_Stopped_ApplicationExit	((2 << 16) + 38)
-#define ADP_Stopped_RunTimeError	((2 << 16) + 35)
+#define AngelSVC_Reason_Open			0x01
+#define AngelSVC_Reason_Close			0x02
+#define AngelSVC_Reason_WriteC			0x03
+#define AngelSVC_Reason_Write0			0x04
+#define AngelSVC_Reason_Write			0x05
+#define AngelSVC_Reason_Read			0x06
+#define AngelSVC_Reason_ReadC			0x07
+#define AngelSVC_Reason_IsError			0x08
+#define AngelSVC_Reason_IsTTY			0x09
+#define AngelSVC_Reason_Seek			0x0A
+#define AngelSVC_Reason_FLen			0x0C
+#define AngelSVC_Reason_TmpNam			0x0D
+#define AngelSVC_Reason_Remove			0x0E
+#define AngelSVC_Reason_Rename			0x0F
+#define AngelSVC_Reason_Clock			0x10
+#define AngelSVC_Reason_Time			0x11
+#define AngelSVC_Reason_System			0x12
+#define AngelSVC_Reason_Errno			0x13
+#define AngelSVC_Reason_GetCmdLine		0x15
+#define AngelSVC_Reason_HeapInfo		0x16
+#define AngelSVC_Reason_EnterSVC		0x17
+#define AngelSVC_Reason_ReportException 	0x18
+#define AngelSVC_Reason_SyncCacheRange		0x19
+#define AngelSVC_Reason_ReportExceptionExtended 0x20
+#define AngelSVC_Reason_Elapsed			0x30
+#define AngelSVC_Reason_TickFreq		0x31
+#define ADP_Stopped_ApplicationExit		((2 << 16) + 38)
+#define ADP_Stopped_RunTimeError		((2 << 16) + 35)
+
+/* Semihosting feature magic numbers.  */
+#define NUM_SHFB_MAGIC			4
+#define SHFB_MAGIC_0			0x53
+#define SHFB_MAGIC_1			0x48
+#define SHFB_MAGIC_2			0x46
+#define SHFB_MAGIC_3			0x42
+
+/* Semihosting extensions.  */
+#define SH_EXT_EXIT_EXTENDED_BITNUM	0x0
+#define SH_EXT_STDOUT_STDERR_BITNUM	0x1
+
+#if !defined (__ASSEMBLER__)
+extern int _get_semihosting_exts _PARAMS ((char*, int, int));
+extern int _has_ext_exit_extended _PARAMS ((void));
+extern int _has_ext_stdout_stderr _PARAMS ((void));
+#endif
 
 #if defined(ARM_RDI_MONITOR) && !defined(__ASSEMBLER__)
 
diff --git a/libgloss/aarch64/syscalls.c b/libgloss/aarch64/syscalls.c
index 058cef5cb94a80f68be6b77192d164df2851f374..af206a1d49fe7113a74c3574bb2e08de2a36096d 100644
--- a/libgloss/aarch64/syscalls.c
+++ b/libgloss/aarch64/syscalls.c
@@ -76,6 +76,9 @@ static int checkerror _PARAMS ((int));
 static int error _PARAMS ((int));
 static int get_errno _PARAMS ((void));
 
+/* Semihosting utilities.  */
+static void initialise_semihosting_exts _PARAMS ((void));
+
 /* Struct used to keep track of the file position, just so we
    can implement fseek(fh,x,SEEK_CUR).  */
 struct fdent
@@ -130,6 +133,9 @@ static int monitor_stdin;
 static int monitor_stdout;
 static int monitor_stderr;
 
+static int supports_ext_exit_extended = -1;
+static int supports_ext_stdout_stderr = -1;
+
 /* Return a pointer to the structure associated with
    the user file descriptor fd. */
 static struct fdent *
@@ -188,32 +194,131 @@ initialise_monitor_handles (void)
   block[1] = 0;			/* mode "r" */
   monitor_stdin = do_AngelSVC (AngelSVC_Reason_Open, block);
 
-  block[0] = POINTER_TO_PARAM_BLOCK_T (":tt");
-  block[2] = 3;			/* length of filename */
-  block[1] = 4;			/* mode "w" */
-  monitor_stdout = do_AngelSVC (AngelSVC_Reason_Open, block);
+  for (i = 0; i < MAX_OPEN_FILES; i++)
+    openfiles[i].handle = -1;;
 
-  block[0] = POINTER_TO_PARAM_BLOCK_T (":tt");
-  block[2] = 3;			/* length of filename */
-  block[1] = 8;			/* mode "a" */
-  monitor_stderr = do_AngelSVC (AngelSVC_Reason_Open, block);
+  if (_has_ext_stdout_stderr ())
+  {
+    block[0] = POINTER_TO_PARAM_BLOCK_T (":tt");
+    block[2] = 3;			/* length of filename */
+    block[1] = 4;			/* mode "w" */
+    monitor_stdout = do_AngelSVC (AngelSVC_Reason_Open, block);
+
+    block[0] = POINTER_TO_PARAM_BLOCK_T (":tt");
+    block[2] = 3;			/* length of filename */
+    block[1] = 8;			/* mode "a" */
+    monitor_stderr = do_AngelSVC (AngelSVC_Reason_Open, block);
+  }
 
   /* If we failed to open stderr, redirect to stdout. */
   if (monitor_stderr == -1)
     monitor_stderr = monitor_stdout;
 
-  for (i = 0; i < MAX_OPEN_FILES; i++)
-    openfiles[i].handle = -1;
-
   openfiles[0].handle = monitor_stdin;
   openfiles[0].flags = _FREAD;
   openfiles[0].pos = 0;
-  openfiles[1].handle = monitor_stdout;
-  openfiles[0].flags = _FWRITE;
-  openfiles[1].pos = 0;
-  openfiles[2].handle = monitor_stderr;
-  openfiles[0].flags = _FWRITE;
-  openfiles[2].pos = 0;
+
+  if (_has_ext_stdout_stderr ())
+  {
+    openfiles[1].handle = monitor_stdout;
+    openfiles[0].flags = _FWRITE;
+    openfiles[1].pos = 0;
+    openfiles[2].handle = monitor_stderr;
+    openfiles[0].flags = _FWRITE;
+    openfiles[2].pos = 0;
+  }
+}
+
+int
+_has_ext_exit_extended (void)
+{
+  if (supports_ext_exit_extended < 0)
+  {
+    initialise_semihosting_exts ();
+  }
+
+  return supports_ext_exit_extended;
+}
+
+int
+_has_ext_stdout_stderr (void)
+{
+  if (supports_ext_stdout_stderr < 0)
+  {
+    initialise_semihosting_exts ();
+  }
+
+  return supports_ext_stdout_stderr;
+}
+
+static void
+initialise_semihosting_exts (void)
+{
+  supports_ext_exit_extended = 0;
+  supports_ext_stdout_stderr = 1;
+
+#if SEMIHOST_V2
+  char features[1];
+  if (_get_semihosting_exts (features, 0, 1) > 0)
+  {
+     supports_ext_exit_extended
+       = features[0] & (1 << SH_EXT_EXIT_EXTENDED_BITNUM);
+     supports_ext_stdout_stderr
+       = features[0] & (1 << SH_EXT_STDOUT_STDERR_BITNUM);
+  }
+#endif
+}
+
+int
+_get_semihosting_exts (char* features, int offset, int num)
+{
+  int fd = _open (":semihosting-features", O_RDONLY);
+  memset (features, 0, num);
+
+  if (fd == -1)
+  {
+    return -1;
+  }
+
+  struct fdent *pfd;
+  pfd = findslot (fd);
+
+  param_block_t block[1];
+  block[0] = pfd->handle;
+
+  int len = do_AngelSVC (AngelSVC_Reason_FLen, block);
+
+  if (len < NUM_SHFB_MAGIC
+      || num > (len - NUM_SHFB_MAGIC))
+  {
+     _close (fd);
+     return -1;
+  }
+
+  char buffer[NUM_SHFB_MAGIC];
+  int n_read = _read (fd, buffer, NUM_SHFB_MAGIC);
+
+  if (n_read < NUM_SHFB_MAGIC
+      || buffer[0] != SHFB_MAGIC_0
+      || buffer[1] != SHFB_MAGIC_1
+      || buffer[2] != SHFB_MAGIC_2
+      || buffer[3] != SHFB_MAGIC_3)
+  {
+     _close (fd);
+     return -1;
+  }
+
+  if (_lseek (fd, offset, SEEK_CUR) < 0)
+  {
+     _close (fd);
+     return -1;
+  }
+
+  n_read = _read (fd, features, num);
+
+  _close (fd);
+
+  return checkerror (n_read);
 }
 
 static int

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]