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];
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);
}
}

View File

@ -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);
}

View File

@ -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__)

View File

@ -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