public inbox for newlib@sourceware.org
 help / color / mirror / Atom feed
From: Craig Blackmore <craig.blackmore@embecosm.com>
To: Jeff Johnston <jjohnstn@redhat.com>
Cc: Newlib <newlib@sourceware.org>
Subject: Re: [PATCH] RISC-V: Add semihosting support
Date: Wed, 16 Dec 2020 08:33:02 +0000	[thread overview]
Message-ID: <3ef25bfd-65d7-e8a2-cdd6-0b0532b5c4f6@embecosm.com> (raw)
In-Reply-To: <CAOox84tU+8Tx-M6bB6cTFcj+TbwHvYKDCVfvhmozn9cb5ekbGA@mail.gmail.com>

Hi Jeff,

On 15/12/2020 22:51, Jeff Johnston wrote:
> Hi Craig,
>
> Can you confirm that you have permission from your employer (embecosm)
> to contribute the code?  Other than that, I think we're good to merge
> before the snapshot.

Yes, I have permission from Embecosm to contribute this.

Thanks,

Craig

>
> Thanks,
>
> -- Jeff J.
>
> On Tue, Dec 15, 2020 at 7:00 AM Craig Blackmore
> <craig.blackmore@embecosm.com <mailto:craig.blackmore@embecosm.com>>
> wrote:
>
>     Hi Kito,
>
>     Thanks for the test and review.
>
>     On 09/12/2020 08:21, Kito Cheng wrote:
>
>     > Hi Craig:
>     >
>     > I verified with GCC testsuite on qemu with Keith's semihosting
>     patch,
>     > And that's LGTM, only two minor review comment, see below:
>     >
>     >> +++ b/libgloss/riscv/semihost-sys_exit.c
>     >> @@ -0,0 +1,19 @@
>     >> +#include <machine/syscall.h>
>     >> +#include "semihost_syscall.h"
>     >> +
>     >> +#define ADP_Stopped_ApplicationExit 0x20026
>     >> +
>     >> +/* Exit a program without cleaning up files.  */
>     >> +void
>     >> +_exit (int exit_status)
>     >> +{
>     >> +#if __riscv_xlen == 32
>     >> +  syscall_errno (SEMIHOST_exit, (long *)
>     ADP_Stopped_ApplicationExit);
>     > Could you use SEMIHOST_exit_extended here, so that we could have
>     > return value on rv32.
>
>     I can use SEMIHOST_exit_extended, but I will also need to add a
>     check for the
>     SH_EXT_EXIT_EXTENDED feature. Can I follow up with this in a later
>     patch?
>
>     >> +/* Return the fdentry for file or NULL if not found.  */
>     >> +
>     >> +struct fdentry *
>     >> +__get_fdentry (int file)
>     >> +{
>     >> +  if (file<0 || file>RISCV_MAX_OPEN_FILES ||
>     fdtable[file].handle == -1)
>     > Should be >= RISCV_MAX_OPEN_FILES here?
>
>     Please see updated patch below which fixes this condition and adds
>     a license as
>     requested by Jeff Johnston.
>
>     Best wishes,
>     Craig
>
>     ---
>      libgloss/riscv/Makefile.in                | 66 +++++++++++++++++-
>      libgloss/riscv/machine/syscall.h          | 25 +++++++
>      libgloss/riscv/semihost-sys_close.c       | 28 ++++++++
>      libgloss/riscv/semihost-sys_exit.c        | 23 ++++++
>      libgloss/riscv/semihost-sys_fdtable.c     | 85
>     +++++++++++++++++++++++
>      libgloss/riscv/semihost-sys_fstat.c       | 19 +++++
>      libgloss/riscv/semihost-sys_ftime.c       | 16 +++++
>      libgloss/riscv/semihost-sys_isatty.c      | 21 ++++++
>      libgloss/riscv/semihost-sys_link.c        |  9 +++
>      libgloss/riscv/semihost-sys_lseek.c       | 70 +++++++++++++++++++
>      libgloss/riscv/semihost-sys_open.c        | 62 +++++++++++++++++
>      libgloss/riscv/semihost-sys_read.c        | 32 +++++++++
>      libgloss/riscv/semihost-sys_sbrk.c        | 26 +++++++
>      libgloss/riscv/semihost-sys_stat.c        | 36 ++++++++++
>      libgloss/riscv/semihost-sys_stat_common.c | 36 ++++++++++
>      libgloss/riscv/semihost-sys_unlink.c      | 15 ++++
>      libgloss/riscv/semihost-sys_write.c       | 32 +++++++++
>      libgloss/riscv/semihost.specs             | 10 +++
>      libgloss/riscv/semihost_fdtable.h         | 21 ++++++
>      libgloss/riscv/semihost_stat.h            | 14 ++++
>      libgloss/riscv/semihost_syscall.h         | 47 +++++++++++++
>      21 files changed, 692 insertions(+), 1 deletion(-)
>      create mode 100644 libgloss/riscv/semihost-sys_close.c
>      create mode 100644 libgloss/riscv/semihost-sys_exit.c
>      create mode 100644 libgloss/riscv/semihost-sys_fdtable.c
>      create mode 100644 libgloss/riscv/semihost-sys_fstat.c
>      create mode 100644 libgloss/riscv/semihost-sys_ftime.c
>      create mode 100644 libgloss/riscv/semihost-sys_isatty.c
>      create mode 100644 libgloss/riscv/semihost-sys_link.c
>      create mode 100644 libgloss/riscv/semihost-sys_lseek.c
>      create mode 100644 libgloss/riscv/semihost-sys_open.c
>      create mode 100644 libgloss/riscv/semihost-sys_read.c
>      create mode 100644 libgloss/riscv/semihost-sys_sbrk.c
>      create mode 100644 libgloss/riscv/semihost-sys_stat.c
>      create mode 100644 libgloss/riscv/semihost-sys_stat_common.c
>      create mode 100644 libgloss/riscv/semihost-sys_unlink.c
>      create mode 100644 libgloss/riscv/semihost-sys_write.c
>      create mode 100644 libgloss/riscv/semihost.specs
>      create mode 100644 libgloss/riscv/semihost_fdtable.h
>      create mode 100644 libgloss/riscv/semihost_stat.h
>      create mode 100644 libgloss/riscv/semihost_syscall.h
>
>     diff --git a/libgloss/riscv/Makefile.in b/libgloss/riscv/Makefile.in
>     index 579dd9554..185b6e6d2 100644
>     --- a/libgloss/riscv/Makefile.in
>     +++ b/libgloss/riscv/Makefile.in
>     @@ -40,8 +40,38 @@ gloss_srcs = \
>             sys_wait.c \
>             sys_write.c
>
>     +# libsemihost reuses some of the libgloss minimal implementations
>     +
>     +semihost_srcs = \
>     +       nanosleep.c \
>     +       sys_chdir.c \
>     +       sys_chmod.c \
>     +       sys_chown.c \
>     +       sys_execve.c \
>     +       sys_fork.c \
>     +       sys_getcwd.c \
>     +       sys_getpid.c \
>     +       sys_kill.c \
>     +       sys_utime.c \
>     +       sys_wait.c \
>     +       semihost-sys_close.c \
>     +       semihost-sys_exit.c \
>     +       semihost-sys_fdtable.c \
>     +       semihost-sys_fstat.c \
>     +       semihost-sys_ftime.c \
>     +       semihost-sys_isatty.c \
>     +       semihost-sys_link.c \
>     +       semihost-sys_lseek.c \
>     +       semihost-sys_open.c \
>     +       semihost-sys_read.c \
>     +       semihost-sys_sbrk.c \
>     +       semihost-sys_stat.c \
>     +       semihost-sys_stat_common.c \
>     +       semihost-sys_unlink.c \
>     +       semihost-sys_write.c
>     +
>      gloss_specs = \
>     -       nano.specs sim.specs
>     +       nano.specs sim.specs semihost.specs
>
>      # Extra files
>
>     @@ -134,6 +164,17 @@ sim_objs += $(sim_c_objs)
>      deps += $(sim_c_deps)
>      junk += $(sim_c_deps) $(sim_c_objs)
>
>     +semihost_c_srcs = $(filter %.c, $(semihost_srcs))
>     +semihost_c_objs = $(patsubst %.c, semihost-%.o, $(notdir
>     $(semihost_c_srcs)))
>     +semihost_c_deps = $(patsubst %.c, semihost-%.d, $(notdir
>     $(semihost_c_srcs)))
>     +
>     +$(semihost_c_objs): semihost-%.o : %.c
>     +       $(COMPILE) -c -o $@ $<
>     +
>     +semihost_objs += $(semihost_c_objs)
>     +deps += $(semihost_c_deps)
>     +junk += $(semihost_c_deps) $(semihost_c_objs)
>     +
>      #-------------------------------------------------------------------------
>      # Build Object Files from Assembly Source
>      #-------------------------------------------------------------------------
>     @@ -159,6 +200,16 @@ sim_objs += $(sim_asm_objs)
>      deps += $(sim_asm_deps)
>      junk += $(sim_asm_deps) $(sim_asm_objs)
>
>     +semihost_asm_objs = $(patsubst %.S, semihost-%.o, $(notdir
>     $(gloss_asm_srcs)))
>     +semihost_asm_deps = $(patsubst %.S, semihost-%.d, $(notdir
>     $(gloss_asm_srcs)))
>     +
>     +$(semihost_asm_objs) : semihost-%.o : %.S
>     +       $(COMPILE) -c -DUSING_SEMIHOST_SPECS -o $@ $<
>     +
>     +semihost_objs += $(semihost_asm_objs)
>     +deps += $(semihost_asm_deps)
>     +junk += $(semihost_asm_deps) $(semihost_asm_objs)
>     +
>      #-------------------------------------------------------------------------
>      # Build libgloss.a
>      #-------------------------------------------------------------------------
>     @@ -187,6 +238,19 @@ junk += $(sim_lib)
>
>      install_libs += $(sim_lib)
>
>     +#-------------------------------------------------------------------------
>     +# Build libsemihost.a
>     +#-------------------------------------------------------------------------
>     +
>     +semihost_lib  = libsemihost.a
>     +$(semihost_lib) : $(semihost_objs)
>     +       $(AR) rcv $@ $^
>     +       $(RANLIB) $@
>     +
>     +junk += $(semihost_lib)
>     +
>     +install_libs += $(semihost_lib)
>     +
>      #-------------------------------------------------------------------------
>      # Build crt0.o
>      #-------------------------------------------------------------------------
>     diff --git a/libgloss/riscv/machine/syscall.h
>     b/libgloss/riscv/machine/syscall.h
>     index 5cd15b848..88b9fdfda 100644
>     --- a/libgloss/riscv/machine/syscall.h
>     +++ b/libgloss/riscv/machine/syscall.h
>     @@ -54,4 +54,29 @@
>      #define SYS_time 1062
>      #define SYS_getmainvars 2011
>
>     +/* Semihosting operations.  */
>     +#define SEMIHOST_clock 0x10
>     +#define SEMIHOST_close 0x02
>     +#define SEMIHOST_elapsed 0x30
>     +#define SEMIHOST_errno 0x13
>     +#define SEMIHOST_exit 0x18
>     +#define SEMIHOST_exit_extended 0x20
>     +#define SEMIHOST_flen 0x0C
>     +#define SEMIHOST_get_cmdline 0x15
>     +#define SEMIHOST_heapinfo 0x16
>     +#define SEMIHOST_iserror 0x08
>     +#define SEMIHOST_istty 0x09
>     +#define SEMIHOST_open 0x01
>     +#define SEMIHOST_read 0x06
>     +#define SEMIHOST_readc 0x07
>     +#define SEMIHOST_remove 0x0E
>     +#define SEMIHOST_rename 0x0F
>     +#define SEMIHOST_seek 0x0A
>     +#define SEMIHOST_system 0x12
>     +#define SEMIHOST_tickfreq 0x31
>     +#define SEMIHOST_time 0x11
>     +#define SEMIHOST_tmpnam 0x0D
>     +#define SEMIHOST_write 0x05
>     +#define SEMIHOST_writec 0x03
>     +#define SEMIHOST_write0 0x04
>      #endif
>     diff --git a/libgloss/riscv/semihost-sys_close.c
>     b/libgloss/riscv/semihost-sys_close.c
>     new file mode 100644
>     index 000000000..47402340c
>     --- /dev/null
>     +++ b/libgloss/riscv/semihost-sys_close.c
>     @@ -0,0 +1,28 @@
>     +/*
>     + * Copyright (C) 2020 Embecosm Limited
>     + * SPDX-License-Identifier: BSD-2-Clause
>     + */
>     +#include <machine/syscall.h>
>     +#include "semihost_syscall.h"
>     +#include "semihost_fdtable.h"
>     +
>     +/* Close a file.  */
>     +int
>     +_close (int file)
>     +{
>     +  long res;
>     +  struct fdentry *fd =__get_fdentry (file);
>     +  long data_block[1];
>     +
>     +  if (fd == NULL)
>     +    return -1;
>     +
>     +  data_block[0] = fd->handle;
>     +  res = syscall_errno (SEMIHOST_close, data_block);
>     +
>     +  if (res != 0)
>     +    return res;
>     +
>     +  __remove_fdentry (file);
>     +  return 0;
>     +}
>     diff --git a/libgloss/riscv/semihost-sys_exit.c
>     b/libgloss/riscv/semihost-sys_exit.c
>     new file mode 100644
>     index 000000000..626fb6aeb
>     --- /dev/null
>     +++ b/libgloss/riscv/semihost-sys_exit.c
>     @@ -0,0 +1,23 @@
>     +/*
>     + * Copyright (C) 2020 Embecosm Limited
>     + * SPDX-License-Identifier: BSD-2-Clause
>     + */
>     +#include <machine/syscall.h>
>     +#include "semihost_syscall.h"
>     +
>     +#define ADP_Stopped_ApplicationExit 0x20026
>     +
>     +/* Exit a program without cleaning up files.  */
>     +void
>     +_exit (int exit_status)
>     +{
>     +#if __riscv_xlen == 32
>     +  syscall_errno (SEMIHOST_exit, (long *)
>     ADP_Stopped_ApplicationExit);
>     +#else
>     +  /* The semihosting exit operation only allows 64-bit targets to
>     report the
>     +     exit code.  */
>     +  long data_block[] = {ADP_Stopped_ApplicationExit, exit_status};
>     +  syscall_errno (SEMIHOST_exit, data_block);
>     +#endif
>     +  while (1);
>     +}
>     diff --git a/libgloss/riscv/semihost-sys_fdtable.c
>     b/libgloss/riscv/semihost-sys_fdtable.c
>     new file mode 100644
>     index 000000000..152c92d15
>     --- /dev/null
>     +++ b/libgloss/riscv/semihost-sys_fdtable.c
>     @@ -0,0 +1,85 @@
>     +/*
>     + * Copyright (C) 2020 Embecosm Limited
>     + * SPDX-License-Identifier: BSD-2-Clause
>     + */
>     +#include "semihost_fdtable.h"
>     +#include <errno.h>
>     +#include <fcntl.h>
>     +#include <unistd.h>
>     +
>     +#ifndef RISCV_MAX_OPEN_FILES
>     +#define RISCV_MAX_OPEN_FILES 16
>     +#endif
>     +
>     +extern int errno;
>     +extern int _open (const char *, int, ...);
>     +
>     +/* fdtable keeps track of the position of each file and is used
>     to map stdin,
>     +   stdout and stderr to STDIN_FILENO, STDOUT_FILENO and
>     STDERR_FILENO.  */
>     +
>     +static struct fdentry fdtable[RISCV_MAX_OPEN_FILES];
>     +
>     +/* Initialize fdtable.  A handle of -1 denotes an empty entry.  */
>     +
>     +void __attribute__ ((constructor))
>     +init_semihosting ()
>     +{
>     +  int handle;
>     +
>     +  for (int i=0; i<RISCV_MAX_OPEN_FILES; i++)
>     +    fdtable[i].handle = -1;
>     +
>     +  /* Set up std streams.  */
>     +  /* stdin.  */
>     +  handle = _open (":tt", O_RDONLY);
>     +  fdtable[STDIN_FILENO].handle = handle;
>     +  fdtable[STDIN_FILENO].pos = 0;
>     +
>     +  /* stdout.  */
>     +  handle = _open (":tt", O_WRONLY|O_CREAT|O_TRUNC);
>     +  fdtable[STDOUT_FILENO].handle = handle;
>     +  fdtable[STDOUT_FILENO].pos = 0;
>     +
>     +  /* stderr.  */
>     +  handle = _open (":tt", O_WRONLY|O_CREAT|O_APPEND);
>     +  fdtable[STDERR_FILENO].handle = handle;
>     +  fdtable[STDERR_FILENO].pos = 0;
>     +}
>     +
>     +/* Add entry to fdtable.  */
>     +
>     +int
>     +__add_fdentry (int handle)
>     +{
>     +  for (int i=0; i<RISCV_MAX_OPEN_FILES; i++)
>     +    if (fdtable[i].handle == -1)
>     +      {
>     +       fdtable[i].handle = handle;
>     +       fdtable[i].pos = 0;
>     +       return i;
>     +      }
>     +  /* Too many open files.  */
>     +  errno = ENFILE;
>     +  return -1;
>     +}
>     +
>     +/* Return the fdentry for file or NULL if not found.  */
>     +
>     +struct fdentry *
>     +__get_fdentry (int file)
>     +{
>     +  if (file<0 || file>=RISCV_MAX_OPEN_FILES ||
>     fdtable[file].handle == -1)
>     +    {
>     +      errno = EBADF;
>     +      return NULL;
>     +    }
>     +  return &fdtable[file];
>     +}
>     +
>     +/* Remove entry from fdtable.  */
>     +
>     +void
>     +__remove_fdentry (int file)
>     +{
>     +  fdtable[file].handle = -1;
>     +}
>     diff --git a/libgloss/riscv/semihost-sys_fstat.c
>     b/libgloss/riscv/semihost-sys_fstat.c
>     new file mode 100644
>     index 000000000..f57f0c07f
>     --- /dev/null
>     +++ b/libgloss/riscv/semihost-sys_fstat.c
>     @@ -0,0 +1,19 @@
>     +/*
>     + * Copyright (C) 2020 Embecosm Limited
>     + * SPDX-License-Identifier: BSD-2-Clause
>     + */
>     +#include <string.h>
>     +#include <sys/stat.h>
>     +#include "semihost_stat.h"
>     +
>     +/* Status of an open file.  The sys/stat.h header file required is
>     +   distributed in the include subdirectory for this C library.  */
>     +
>     +int
>     +_fstat (int file, struct stat *st)
>     +{
>     +  /* Initialize st as not all fields will be set.  */
>     +  memset (st, 0, sizeof (*st));
>     +
>     +  return __stat_common (file, st);
>     +}
>     diff --git a/libgloss/riscv/semihost-sys_ftime.c
>     b/libgloss/riscv/semihost-sys_ftime.c
>     new file mode 100644
>     index 000000000..aeafc6ca2
>     --- /dev/null
>     +++ b/libgloss/riscv/semihost-sys_ftime.c
>     @@ -0,0 +1,16 @@
>     +/*
>     + * Copyright (C) 2020 Embecosm Limited
>     + * SPDX-License-Identifier: BSD-2-Clause
>     + */
>     +#include <machine/syscall.h>
>     +#include <sys/timeb.h>
>     +#include "semihost_syscall.h"
>     +
>     +/* Get the current time.  */
>     +int
>     +_ftime (struct timeb *tp)
>     +{
>     +  tp->time = syscall_errno (SEMIHOST_time, 0);
>     +  tp->millitm = 0;
>     +  return 0;
>     +}
>     diff --git a/libgloss/riscv/semihost-sys_isatty.c
>     b/libgloss/riscv/semihost-sys_isatty.c
>     new file mode 100644
>     index 000000000..02d8e39cb
>     --- /dev/null
>     +++ b/libgloss/riscv/semihost-sys_isatty.c
>     @@ -0,0 +1,21 @@
>     +/*
>     + * Copyright (C) 2020 Embecosm Limited
>     + * SPDX-License-Identifier: BSD-2-Clause
>     + */
>     +#include <machine/syscall.h>
>     +#include <sys/stat.h>
>     +#include "semihost_syscall.h"
>     +#include "semihost_fdtable.h"
>     +
>     +int
>     +_isatty (int file)
>     +{
>     +  struct fdentry *fd =__get_fdentry (file);
>     +  long data_block[1];
>     +
>     +  if (fd == NULL)
>     +    return -1;
>     +
>     +  data_block[0] = fd->handle;
>     +  return syscall_errno (SEMIHOST_istty, data_block);
>     +}
>     diff --git a/libgloss/riscv/semihost-sys_link.c
>     b/libgloss/riscv/semihost-sys_link.c
>     new file mode 100644
>     index 000000000..717c5c81c
>     --- /dev/null
>     +++ b/libgloss/riscv/semihost-sys_link.c
>     @@ -0,0 +1,9 @@
>     +/*
>     + * Copyright (C) 2020 Embecosm Limited
>     + * SPDX-License-Identifier: BSD-2-Clause
>     + */
>     +/* Establish a new name for an existing file.  */
>     +int _link (const char *old_name, const char *new_name)
>     +{
>     +  return -1;
>     +}
>     diff --git a/libgloss/riscv/semihost-sys_lseek.c
>     b/libgloss/riscv/semihost-sys_lseek.c
>     new file mode 100644
>     index 000000000..68fccf2ff
>     --- /dev/null
>     +++ b/libgloss/riscv/semihost-sys_lseek.c
>     @@ -0,0 +1,70 @@
>     +/*
>     + * Copyright (C) 2020 Embecosm Limited
>     + * SPDX-License-Identifier: BSD-2-Clause
>     + */
>     +#include <machine/syscall.h>
>     +#include <errno.h>
>     +#include <sys/types.h>
>     +#include <unistd.h>
>     +#include "semihost_syscall.h"
>     +#include "semihost_fdtable.h"
>     +
>     +extern int errno;
>     +
>     +/* Set position in a file.  */
>     +off_t
>     +_lseek (int file, off_t offset, int dir)
>     +{
>     +  long data_block[2];
>     +  long flen;
>     +  long res;
>     +  struct fdentry *fd;
>     +  off_t abs_pos;
>     +
>     +  fd =__get_fdentry (file);
>     +  if (fd == NULL)
>     +    {
>     +      errno = EBADF;
>     +      return -1;
>     +    }
>     +
>     +  if (dir == SEEK_CUR && offset == 0)
>     +    return fd->pos;
>     +
>     +  data_block[0] = fd->handle;
>     +
>     +  switch (dir)
>     +    {
>     +      case SEEK_SET:
>     +       abs_pos = offset;
>     +       break;
>     +      case SEEK_CUR:
>     +       abs_pos = fd->pos + offset;
>     +       break;
>     +      case SEEK_END:
>     +       data_block[1] = 0;
>     +       flen = syscall_errno (SEMIHOST_flen, data_block);
>     +       if (flen == -1)
>     +         return -1;
>     +       abs_pos = flen + offset;
>     +       break;
>     +      default:
>     +       errno = EINVAL;
>     +       return -1;
>     +    }
>     +
>     +  if (abs_pos < 0)
>     +    {
>     +      errno = EINVAL;
>     +      return -1;
>     +    }
>     +
>     +  data_block[1] = abs_pos;
>     +  res = syscall_errno (SEMIHOST_seek, data_block);
>     +  if (res == 0)
>     +    {
>     +      fd->pos = abs_pos;
>     +      return abs_pos;
>     +    }
>     +  return res;
>     +}
>     diff --git a/libgloss/riscv/semihost-sys_open.c
>     b/libgloss/riscv/semihost-sys_open.c
>     new file mode 100644
>     index 000000000..22f1d8206
>     --- /dev/null
>     +++ b/libgloss/riscv/semihost-sys_open.c
>     @@ -0,0 +1,62 @@
>     +/*
>     + * Copyright (C) 2020 Embecosm Limited
>     + * SPDX-License-Identifier: BSD-2-Clause
>     + */
>     +#include <machine/syscall.h>
>     +#include "semihost_syscall.h"
>     +#include "semihost_fdtable.h"
>     +#include <errno.h>
>     +#include <string.h>
>     +#include <fcntl.h>
>     +
>     +extern int errno;
>     +
>     +#define SEMIHOST_MODE_R 0
>     +#define SEMIHOST_MODE_RPLUS 2
>     +#define SEMIHOST_MODE_W 4
>     +#define SEMIHOST_MODE_WPLUS 6
>     +#define SEMIHOST_MODE_A 8
>     +#define SEMIHOST_MODE_APLUS 10
>     +
>     +/* Open a file.  */
>     +int
>     +_open (const char *name, int flags, ...)
>     +{
>     +  int fh;
>     +  int mode;
>     +  long data_block[3];
>     +
>     +  /* Work out mode from flags.  */
>     +  if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY)
>     +    mode = SEMIHOST_MODE_R;
>     +  else if ((flags & (O_WRONLY | O_CREAT | O_TRUNC))
>     +          == (O_WRONLY | O_CREAT | O_TRUNC))
>     +    mode = SEMIHOST_MODE_W;
>     +  else if ((flags & (O_WRONLY | O_CREAT | O_APPEND))
>     +          == (O_WRONLY | O_CREAT | O_APPEND))
>     +    mode = SEMIHOST_MODE_A;
>     +  else if ((flags & (O_RDWR | O_CREAT | O_TRUNC))
>     +          == (O_RDWR | O_CREAT | O_TRUNC))
>     +    mode = SEMIHOST_MODE_WPLUS;
>     +  else if ((flags & (O_RDWR | O_CREAT | O_APPEND))
>     +          == (O_RDWR | O_CREAT | O_APPEND))
>     +    mode = SEMIHOST_MODE_APLUS;
>     +  else if (flags & O_RDWR)
>     +    mode = SEMIHOST_MODE_RPLUS;
>     +  else
>     +    {
>     +      errno = EINVAL;
>     +      return -1;
>     +    }
>     +
>     +  data_block[0] = (long) name;
>     +  data_block[1] = mode;
>     +  data_block[2] = strlen (name);
>     +  fh = syscall_errno (SEMIHOST_open, data_block);
>     +  /* Failed to open file.  */
>     +  if (fh == -1)
>     +    return -1;
>     +
>     +  /* Register the file in the fdtable.  */
>     +  return __add_fdentry (fh);
>     +}
>     diff --git a/libgloss/riscv/semihost-sys_read.c
>     b/libgloss/riscv/semihost-sys_read.c
>     new file mode 100644
>     index 000000000..3164eed56
>     --- /dev/null
>     +++ b/libgloss/riscv/semihost-sys_read.c
>     @@ -0,0 +1,32 @@
>     +/*
>     + * Copyright (C) 2020 Embecosm Limited
>     + * SPDX-License-Identifier: BSD-2-Clause
>     + */
>     +#include <machine/syscall.h>
>     +#include <errno.h>
>     +#include <sys/types.h>
>     +#include "semihost_syscall.h"
>     +#include "semihost_fdtable.h"
>     +
>     +/* Read from a file.  */
>     +ssize_t _read (int file, void *ptr, size_t len)
>     +{
>     +  struct fdentry *fd =__get_fdentry (file);
>     +  long data_block[3];
>     +  long res;
>     +
>     +  if (fd == NULL)
>     +    return -1;
>     +
>     +  data_block[0] = fd->handle;
>     +  data_block[1] = (long) ptr;
>     +  data_block[2] = len;
>     +  res = syscall_errno (SEMIHOST_read, data_block);
>     +  if (res >= 0)
>     +    {
>     +      ssize_t bytes_read = len - res;
>     +      fd->pos += bytes_read;
>     +      return bytes_read;
>     +    }
>     +  return -1;
>     +}
>     diff --git a/libgloss/riscv/semihost-sys_sbrk.c
>     b/libgloss/riscv/semihost-sys_sbrk.c
>     new file mode 100644
>     index 000000000..cbd035832
>     --- /dev/null
>     +++ b/libgloss/riscv/semihost-sys_sbrk.c
>     @@ -0,0 +1,26 @@
>     +/*
>     + * Copyright (C) 2020 Embecosm Limited
>     + * SPDX-License-Identifier: BSD-2-Clause
>     + */
>     +/* Semihosting requires that sbrk be implemented without a
>     syscall.  */
>     +extern char _end[];               /* _end is set in the linker
>     command file.  */
>     +char *heap_ptr;
>     +
>     +/*
>     + * sbrk -- changes heap size size.  Get nbytes more
>     + *         RAM.  We just increment a pointer in what's
>     + *         left of memory on the board.
>     + */
>     +char *
>     +_sbrk (nbytes)
>     +     int nbytes;
>     +{
>     +  char *base;
>     +
>     +  if (!heap_ptr)
>     +    heap_ptr = (char *)&_end;
>     +  base = heap_ptr;
>     +  heap_ptr += nbytes;
>     +
>     +  return base;
>     +}
>     diff --git a/libgloss/riscv/semihost-sys_stat.c
>     b/libgloss/riscv/semihost-sys_stat.c
>     new file mode 100644
>     index 000000000..4015801b9
>     --- /dev/null
>     +++ b/libgloss/riscv/semihost-sys_stat.c
>     @@ -0,0 +1,36 @@
>     +/*
>     + * Copyright (C) 2020 Embecosm Limited
>     + * SPDX-License-Identifier: BSD-2-Clause
>     + */
>     +#include <machine/syscall.h>
>     +#include <string.h>
>     +#include <fcntl.h>
>     +#include "semihost_stat.h"
>     +
>     +/* Status of a file (by name).  */
>     +
>     +int
>     +_stat (const char *name, struct stat *st)
>     +{
>     +  int file;
>     +  int res;
>     +
>     +  /* Initialize st as not all fields will be set.  */
>     +  memset (st, 0, sizeof (*st));
>     +
>     +  /* Try to open file.  */
>     +  file = _open (name, O_RDONLY);
>     +  if (file == -1)
>     +    /* _open should have already set errno.  */
>     +    return -1;
>     +
>     +  /* File opened successfully, infer read permission for owner
>     and assume it is
>     +     a regular file.  */
>     +  st->st_mode |= S_IREAD | S_IFREG;
>     +
>     +  /* Fill in more info.  */
>     +  res = __stat_common (file, st);
>     +
>     +  _close (file);
>     +  return res;
>     +}
>     diff --git a/libgloss/riscv/semihost-sys_stat_common.c
>     b/libgloss/riscv/semihost-sys_stat_common.c
>     new file mode 100644
>     index 000000000..b38eb0863
>     --- /dev/null
>     +++ b/libgloss/riscv/semihost-sys_stat_common.c
>     @@ -0,0 +1,36 @@
>     +/*
>     + * Copyright (C) 2020 Embecosm Limited
>     + * SPDX-License-Identifier: BSD-2-Clause
>     + */
>     +#include <machine/syscall.h>
>     +#include "semihost_syscall.h"
>     +#include <sys/stat.h>
>     +#include "semihost_fdtable.h"
>     +
>     +/* Used by _fstat and _stat to fill in some common details.  */
>     +
>     +int
>     +__stat_common (int file, struct stat *st)
>     +{
>     +  int flen;
>     +  struct fdentry *fd =__get_fdentry (file);
>     +  long data_block[1];
>     +
>     +  if (fd == NULL)
>     +    return -1;
>     +
>     +  data_block[0] = fd->handle;
>     +
>     +  /* Assume character device and default block size of 4096.  */
>     +  st->st_mode |= S_IFCHR;
>     +  st->st_blksize = 4096;
>     +
>     +  /* Attempt to get length of file.  */
>     +  flen = syscall_errno (SEMIHOST_flen, data_block);
>     +  if (flen == -1)
>     +    return -1;
>     +
>     +  st->st_size = flen;
>     +
>     +  return 0;
>     +}
>     diff --git a/libgloss/riscv/semihost-sys_unlink.c
>     b/libgloss/riscv/semihost-sys_unlink.c
>     new file mode 100644
>     index 000000000..1d2a6a0f9
>     --- /dev/null
>     +++ b/libgloss/riscv/semihost-sys_unlink.c
>     @@ -0,0 +1,15 @@
>     +/*
>     + * Copyright (C) 2020 Embecosm Limited
>     + * SPDX-License-Identifier: BSD-2-Clause
>     + */
>     +#include <machine/syscall.h>
>     +#include "semihost_syscall.h"
>     +#include <string.h>
>     +
>     +/* Remove a file's directory entry.  */
>     +int
>     +_unlink (const char *name)
>     +{
>     +  long data_block[] = {(long) name, strlen (name)};
>     +  return syscall_errno (SEMIHOST_remove, data_block);
>     +}
>     diff --git a/libgloss/riscv/semihost-sys_write.c
>     b/libgloss/riscv/semihost-sys_write.c
>     new file mode 100644
>     index 000000000..9aee6d30b
>     --- /dev/null
>     +++ b/libgloss/riscv/semihost-sys_write.c
>     @@ -0,0 +1,32 @@
>     +/*
>     + * Copyright (C) 2020 Embecosm Limited
>     + * SPDX-License-Identifier: BSD-2-Clause
>     + */
>     +#include <machine/syscall.h>
>     +#include <sys/types.h>
>     +#include "semihost_syscall.h"
>     +#include "semihost_fdtable.h"
>     +
>     +/* Write to a file.  */
>     +ssize_t
>     +_write (int file, const void *ptr, size_t len)
>     +{
>     +  struct fdentry *fd =__get_fdentry (file);
>     +  long data_block[3];
>     +  long res;
>     +
>     +  if (fd == NULL)
>     +    return -1;
>     +
>     +  data_block[0] = fd->handle;
>     +  data_block[1] = (long) ptr;
>     +  data_block[2] = len;
>     +  res = syscall_errno (SEMIHOST_write, data_block);
>     +  if (res >= 0)
>     +    {
>     +      ssize_t bytes_written = len - res;
>     +      fd->pos += bytes_written;
>     +      return bytes_written;
>     +    }
>     +  return -1;
>     +}
>     diff --git a/libgloss/riscv/semihost.specs
>     b/libgloss/riscv/semihost.specs
>     new file mode 100644
>     index 000000000..1c86c67e4
>     --- /dev/null
>     +++ b/libgloss/riscv/semihost.specs
>     @@ -0,0 +1,10 @@
>     +# Spec file for semihosting syscalls.
>     +
>     +%rename lib    semihost_lib
>     +%rename link   semihost_link
>     +
>     +*lib:
>     +--start-group -lc -lsemihost --end-group
>     +
>     +*link:
>     +%(semihost_link) %:replace-outfile(-lgloss -lsemihost)
>     diff --git a/libgloss/riscv/semihost_fdtable.h
>     b/libgloss/riscv/semihost_fdtable.h
>     new file mode 100644
>     index 000000000..f596a409a
>     --- /dev/null
>     +++ b/libgloss/riscv/semihost_fdtable.h
>     @@ -0,0 +1,21 @@
>     +/*
>     + * Copyright (C) 2020 Embecosm Limited
>     + * SPDX-License-Identifier: BSD-2-Clause
>     + */
>     +#include <sys/types.h>
>     +
>     +#ifndef RISCV_SEMIHOST_FDTABLE_H
>     +#define RISCV_SEMIHOST_FDTABLE_H
>     +
>     +extern void __attribute__ ((constructor)) init_semihosting ();
>     +extern int __add_fdentry (int);
>     +extern struct fdentry * __get_fdentry (int);
>     +extern void __remove_fdentry (int);
>     +
>     +struct fdentry
>     +{
>     +  int handle;
>     +  off_t pos;
>     +};
>     +
>     +#endif
>     diff --git a/libgloss/riscv/semihost_stat.h
>     b/libgloss/riscv/semihost_stat.h
>     new file mode 100644
>     index 000000000..c040fe8e7
>     --- /dev/null
>     +++ b/libgloss/riscv/semihost_stat.h
>     @@ -0,0 +1,14 @@
>     +/*
>     + * Copyright (C) 2020 Embecosm Limited
>     + * SPDX-License-Identifier: BSD-2-Clause
>     + */
>     +#include <sys/types.h>
>     +
>     +#ifndef RISCV_SEMIHOST_STAT_H
>     +#define RISCV_SEMIHOST_STAT_H
>     +
>     +extern int __stat_common (int, struct stat *);
>     +extern int _open (const char *, int, ...);
>     +extern int _close (int);
>     +
>     +#endif
>     diff --git a/libgloss/riscv/semihost_syscall.h
>     b/libgloss/riscv/semihost_syscall.h
>     new file mode 100644
>     index 000000000..50e731b40
>     --- /dev/null
>     +++ b/libgloss/riscv/semihost_syscall.h
>     @@ -0,0 +1,47 @@
>     +/*
>     + * Copyright (C) 2020 Embecosm Limited
>     + * SPDX-License-Identifier: BSD-2-Clause
>     + */
>     +#ifndef _INTERNAL_SYSCALL_H
>     +#define _INTERNAL_SYSCALL_H
>     +
>     +extern int errno;
>     +
>     +static inline long
>     +__semihost_syscall (long id, long *data_block)
>     +{
>     +  register long a0 asm ("a0") = id;
>     +  register long a1 asm ("a1") = (long) data_block;
>     +
>     +  /* RISC-V semihosting trap sequence.  Must be uncompressed and
>     must not
>     +     cross page boundary.  */
>     +  asm volatile (
>     +    ".balign 16             \n"
>     +    ".option push           \n"
>     +    ".option norvc          \n"
>     +    "slli zero, zero, 0x1f  \n"
>     +    "ebreak                 \n"
>     +    "srai zero, zero, 0x7   \n"
>     +    ".option pop            \n"
>     +      : "+r"(a0) : "r"(a1) : "memory");
>     +
>     +  return a0;
>     +}
>     +
>     +static inline long
>     +__syscall_error ()
>     +{
>     +  errno = __semihost_syscall (SEMIHOST_errno, 0);
>     +  return -1;
>     +}
>     +
>     +static inline long
>     +syscall_errno (long id, long *data_block)
>     +{
>     +  long res = __semihost_syscall (id, data_block);
>     +  if (res < 0)
>     +    return __syscall_error ();
>     +  return res;
>     +}
>     +
>     +#endif
>     -- 
>     2.17.1
>
>

  reply	other threads:[~2020-12-16  8:33 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-11-30 11:36 Craig Blackmore
2020-11-30 14:05 ` Kito Cheng
2020-11-30 19:53 ` Jeff Johnston
2020-12-09  8:21 ` Kito Cheng
2020-12-15 12:00   ` Craig Blackmore
2020-12-15 22:51     ` Jeff Johnston
2020-12-16  8:33       ` Craig Blackmore [this message]
2020-12-16  8:43         ` Kito Cheng
2020-12-16 23:31         ` Jeff Johnston

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3ef25bfd-65d7-e8a2-cdd6-0b0532b5c4f6@embecosm.com \
    --to=craig.blackmore@embecosm.com \
    --cc=jjohnstn@redhat.com \
    --cc=newlib@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).