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;
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[0] = ADP_Stopped_RunTimeError;
block[1] = sig; 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 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"
#define AngelSVCAsm hlt #define AngelSVCAsm hlt
/* The reason codes: */ /* The reason codes: */
#define AngelSVC_Reason_Open 0x01 #define AngelSVC_Reason_Open 0x01
#define AngelSVC_Reason_Close 0x02 #define AngelSVC_Reason_Close 0x02
#define AngelSVC_Reason_WriteC 0x03 #define AngelSVC_Reason_WriteC 0x03
#define AngelSVC_Reason_Write0 0x04 #define AngelSVC_Reason_Write0 0x04
#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_IsTTY 0x09 #define AngelSVC_Reason_IsError 0x08
#define AngelSVC_Reason_Seek 0x0A #define AngelSVC_Reason_IsTTY 0x09
#define AngelSVC_Reason_FLen 0x0C #define AngelSVC_Reason_Seek 0x0A
#define AngelSVC_Reason_TmpNam 0x0D #define AngelSVC_Reason_FLen 0x0C
#define AngelSVC_Reason_Remove 0x0E #define AngelSVC_Reason_TmpNam 0x0D
#define AngelSVC_Reason_Rename 0x0F #define AngelSVC_Reason_Remove 0x0E
#define AngelSVC_Reason_Clock 0x10 #define AngelSVC_Reason_Rename 0x0F
#define AngelSVC_Reason_Time 0x11 #define AngelSVC_Reason_Clock 0x10
#define AngelSVC_Reason_System 0x12 #define AngelSVC_Reason_Time 0x11
#define AngelSVC_Reason_Errno 0x13 #define AngelSVC_Reason_System 0x12
#define AngelSVC_Reason_GetCmdLine 0x15 #define AngelSVC_Reason_Errno 0x13
#define AngelSVC_Reason_HeapInfo 0x16 #define AngelSVC_Reason_GetCmdLine 0x15
#define AngelSVC_Reason_EnterSVC 0x17 #define AngelSVC_Reason_HeapInfo 0x16
#define AngelSVC_Reason_ReportException 0x18 #define AngelSVC_Reason_EnterSVC 0x17
#define AngelSVC_Reason_SyncCacheRange 0x19 #define AngelSVC_Reason_ReportException 0x18
#define AngelSVC_Reason_Elapsed 0x30 #define AngelSVC_Reason_SyncCacheRange 0x19
#define ADP_Stopped_ApplicationExit ((2 << 16) + 38) #define AngelSVC_Reason_ReportExceptionExtended 0x20
#define ADP_Stopped_RunTimeError ((2 << 16) + 35) #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__) #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 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,32 +194,131 @@ 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);
block[0] = POINTER_TO_PARAM_BLOCK_T (":tt"); for (i = 0; i < MAX_OPEN_FILES; i++)
block[2] = 3; /* length of filename */ openfiles[i].handle = -1;;
block[1] = 4; /* mode "w" */
monitor_stdout = do_AngelSVC (AngelSVC_Reason_Open, block);
block[0] = POINTER_TO_PARAM_BLOCK_T (":tt"); if (_has_ext_stdout_stderr ())
block[2] = 3; /* length of filename */ {
block[1] = 8; /* mode "a" */ block[0] = POINTER_TO_PARAM_BLOCK_T (":tt");
monitor_stderr = do_AngelSVC (AngelSVC_Reason_Open, block); 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 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;
openfiles[1].handle = monitor_stdout;
openfiles[0].flags = _FWRITE; if (_has_ext_stdout_stderr ())
openfiles[1].pos = 0; {
openfiles[2].handle = monitor_stderr; openfiles[1].handle = monitor_stdout;
openfiles[0].flags = _FWRITE; openfiles[0].flags = _FWRITE;
openfiles[2].pos = 0; 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 static int