Add support for Semihosting v2 support for AArch64 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.

Signed-off-by: Tamar Christina <tamar.christina@arm.com>
This commit is contained in:
Tamar Christina 2017-07-05 13:04:59 +01:00 committed by Corinna Vinschen
parent d7d6ad7b6b
commit ddb6f8a02a
4 changed files with 186 additions and 47 deletions

View File

@ -36,6 +36,12 @@ _exit (int status)
param_block_t block[2]; param_block_t block[2];
block[0] = ADP_Stopped_ApplicationExit; block[0] = ADP_Stopped_ApplicationExit;
block[1] = status; block[1] = status;
#if SEMIHOST_V2
if (_has_ext_exit_extended ())
do_AngelSVC (AngelSVC_Reason_ReportExceptionExtended, block);
else
#endif
do_AngelSVC (AngelSVC_Reason_ReportException, block); do_AngelSVC (AngelSVC_Reason_ReportException, block);
} }
} }

View File

@ -45,5 +45,11 @@ _kill (int pid, int sig)
block[0] = ADP_Stopped_RunTimeError; block[0] = ADP_Stopped_RunTimeError;
block[1] = sig; block[1] = sig;
#if SEMIHOST_V2
if (_has_ext_exit_extended ())
return do_AngelSVC (AngelSVC_Reason_ReportExceptionExtended, block);
else
#endif
return do_AngelSVC (AngelSVC_Reason_ReportException, block); return do_AngelSVC (AngelSVC_Reason_ReportException, block);
} }

View File

@ -23,6 +23,8 @@
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
#include <_ansi.h>
/* Now the SWI numbers and reason codes for RDI (Angel) monitors. */ /* Now the SWI numbers and reason codes for RDI (Angel) monitors. */
#define AngelSVC 0xF000 #define AngelSVC 0xF000
#define AngelSVCInsn "hlt" #define AngelSVCInsn "hlt"
@ -36,6 +38,7 @@
#define AngelSVC_Reason_Write 0x05 #define AngelSVC_Reason_Write 0x05
#define AngelSVC_Reason_Read 0x06 #define AngelSVC_Reason_Read 0x06
#define AngelSVC_Reason_ReadC 0x07 #define AngelSVC_Reason_ReadC 0x07
#define AngelSVC_Reason_IsError 0x08
#define AngelSVC_Reason_IsTTY 0x09 #define AngelSVC_Reason_IsTTY 0x09
#define AngelSVC_Reason_Seek 0x0A #define AngelSVC_Reason_Seek 0x0A
#define AngelSVC_Reason_FLen 0x0C #define AngelSVC_Reason_FLen 0x0C
@ -51,10 +54,29 @@
#define AngelSVC_Reason_EnterSVC 0x17 #define AngelSVC_Reason_EnterSVC 0x17
#define AngelSVC_Reason_ReportException 0x18 #define AngelSVC_Reason_ReportException 0x18
#define AngelSVC_Reason_SyncCacheRange 0x19 #define AngelSVC_Reason_SyncCacheRange 0x19
#define AngelSVC_Reason_ReportExceptionExtended 0x20
#define AngelSVC_Reason_Elapsed 0x30 #define AngelSVC_Reason_Elapsed 0x30
#define AngelSVC_Reason_TickFreq 0x31
#define ADP_Stopped_ApplicationExit ((2 << 16) + 38) #define ADP_Stopped_ApplicationExit ((2 << 16) + 38)
#define ADP_Stopped_RunTimeError ((2 << 16) + 35) #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__) #if defined(ARM_RDI_MONITOR) && !defined(__ASSEMBLER__)
/* Type of each entry in a parameter block. */ /* Type of each entry in a parameter block. */

View File

@ -76,6 +76,9 @@ static int checkerror _PARAMS ((int));
static int error _PARAMS ((int)); static int error _PARAMS ((int));
static int get_errno _PARAMS ((void)); 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 /* Struct used to keep track of the file position, just so we
can implement fseek(fh,x,SEEK_CUR). */ can implement fseek(fh,x,SEEK_CUR). */
struct fdent struct fdent
@ -130,6 +133,9 @@ static int monitor_stdin;
static int monitor_stdout; static int monitor_stdout;
static int monitor_stderr; 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 /* Return a pointer to the structure associated with
the user file descriptor fd. */ the user file descriptor fd. */
static struct fdent * static struct fdent *
@ -188,6 +194,11 @@ initialise_monitor_handles (void)
block[1] = 0; /* mode "r" */ block[1] = 0; /* mode "r" */
monitor_stdin = do_AngelSVC (AngelSVC_Reason_Open, block); monitor_stdin = do_AngelSVC (AngelSVC_Reason_Open, block);
for (i = 0; i < MAX_OPEN_FILES; i++)
openfiles[i].handle = -1;;
if (_has_ext_stdout_stderr ())
{
block[0] = POINTER_TO_PARAM_BLOCK_T (":tt"); block[0] = POINTER_TO_PARAM_BLOCK_T (":tt");
block[2] = 3; /* length of filename */ block[2] = 3; /* length of filename */
block[1] = 4; /* mode "w" */ block[1] = 4; /* mode "w" */
@ -197,17 +208,18 @@ initialise_monitor_handles (void)
block[2] = 3; /* length of filename */ block[2] = 3; /* length of filename */
block[1] = 8; /* mode "a" */ block[1] = 8; /* mode "a" */
monitor_stderr = do_AngelSVC (AngelSVC_Reason_Open, block); monitor_stderr = do_AngelSVC (AngelSVC_Reason_Open, block);
}
/* If we failed to open stderr, redirect to stdout. */ /* If we failed to open stderr, redirect to stdout. */
if (monitor_stderr == -1) if (monitor_stderr == -1)
monitor_stderr = monitor_stdout; monitor_stderr = monitor_stdout;
for (i = 0; i < MAX_OPEN_FILES; i++)
openfiles[i].handle = -1;
openfiles[0].handle = monitor_stdin; openfiles[0].handle = monitor_stdin;
openfiles[0].flags = _FREAD; openfiles[0].flags = _FREAD;
openfiles[0].pos = 0; openfiles[0].pos = 0;
if (_has_ext_stdout_stderr ())
{
openfiles[1].handle = monitor_stdout; openfiles[1].handle = monitor_stdout;
openfiles[0].flags = _FWRITE; openfiles[0].flags = _FWRITE;
openfiles[1].pos = 0; openfiles[1].pos = 0;
@ -215,6 +227,99 @@ initialise_monitor_handles (void)
openfiles[0].flags = _FWRITE; openfiles[0].flags = _FWRITE;
openfiles[2].pos = 0; 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 static int
get_errno (void) get_errno (void)