236 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			236 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
   Copyright (c) 2015, Synopsys, Inc. All rights reserved.
 | 
						|
 | 
						|
   Redistribution and use in source and binary forms, with or without
 | 
						|
   modification, are permitted provided that the following conditions are met:
 | 
						|
 | 
						|
   1) Redistributions of source code must retain the above copyright notice,
 | 
						|
   this list of conditions and the following disclaimer.
 | 
						|
 | 
						|
   2) Redistributions in binary form must reproduce the above copyright notice,
 | 
						|
   this list of conditions and the following disclaimer in the documentation
 | 
						|
   and/or other materials provided with the distribution.
 | 
						|
 | 
						|
   3) Neither the name of the Synopsys, Inc., nor the names of its contributors
 | 
						|
   may be used to endorse or promote products derived from this software
 | 
						|
   without specific prior written permission.
 | 
						|
 | 
						|
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
						|
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
						|
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
						|
   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 | 
						|
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
						|
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
						|
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
						|
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
						|
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 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>
 | 
						|
#include <_syslist.h>
 | 
						|
#include <errno.h>
 | 
						|
#include <sys/fcntl.h>
 | 
						|
#include <sys/stat.h>
 | 
						|
#include <sys/time.h>
 | 
						|
#include <sys/times.h>
 | 
						|
#include <sys/types.h>
 | 
						|
 | 
						|
#include "glue.h"
 | 
						|
#include "nsim-syscall.h"
 | 
						|
 | 
						|
/* Those system calls are implemented in both nSIM and CGEN.  */
 | 
						|
_syscall3 (_ssize_t, read, int, fd, void *, buf, size_t, count)
 | 
						|
_syscall3 (_ssize_t, write, int, fd, const void *, buf, size_t, count)
 | 
						|
_syscall1 (int, unlink, const char *, pathname)
 | 
						|
_syscall3 (off_t, lseek, int, fd, off_t, offset, int, whence)
 | 
						|
_syscall2 (int, gettimeofday, struct timeval *, tv, void *, tz)
 | 
						|
_syscall1 (_CLOCK_T_, time, _CLOCK_T_ *, t)
 | 
						|
_syscall1 (int, close, int, fd)
 | 
						|
_syscall1 (_CLOCK_T_, times, struct tms *, buf)
 | 
						|
/* stat requires custom implementation.  */
 | 
						|
/* _syscall2 (int, stat, const char *, path, struct stat *, st)
 | 
						|
   _syscall2 (int, fstat, int, file, struct stat *, st) */
 | 
						|
/* nSIM implements brk and sbrk, but instead sbrk.c is used.  */
 | 
						|
/* _syscall1 (int, brk, void *, addr) */
 | 
						|
/* open requires custom implementation.  */
 | 
						|
/* _syscall3 (int, open, const char *, pathname, int, flags, int, mode) */
 | 
						|
 | 
						|
/* Those syscalls are not available in CGEN simulator.  */
 | 
						|
_syscall1 (int, rmdir, const char *, pathname)
 | 
						|
_syscall2 (char *, getcwd, char *, buf, size_t, size)
 | 
						|
/* stat requires custom implementation.  */
 | 
						|
/* _syscall2 (int, lstat, const char *, path, struct stat *, st) */
 | 
						|
 | 
						|
/* Historically "open" flags defined by default in newlib and in Linux for ARC
 | 
						|
   are different - this is true for some other architectures as well, e.g.
 | 
						|
   ARM.  To provide compatibility ARC port of newlib had a custom fcntl.h file
 | 
						|
   that has "open" flags identical to Linux ones.  Some other architectures
 | 
						|
   (spart64, cris) override default fcntl.h as well, but I'm not sure this is
 | 
						|
   really a good idea.  Unlike system call numbers that can be unique to each
 | 
						|
   BSP in libgloss, "open" flags are not abstracted from the application code
 | 
						|
   itself, hence it is not possible to have fcntl.h in the libgloss.  To make
 | 
						|
   matters worse, existing simulators already has been built for the Linux-like
 | 
						|
   "open" flags.  To preserve compatibility with existing hostlink
 | 
						|
   implementations in simulators, but avoid custom fcntl.h in the future,
 | 
						|
   simulator BSP has to do dynamic rewriting of "open" flags from the newlib
 | 
						|
   default into old ARC Linux flags.  Simulators support only most basic flags,
 | 
						|
   therefore only those are translated in this implementation.  */
 | 
						|
int
 | 
						|
_open (const char * pathname, int flags, int mode)
 | 
						|
{
 | 
						|
  int nsim_flags = 0;
 | 
						|
 | 
						|
  /* RDONLY, WRONLY, RDWR are same as newlib default.  */
 | 
						|
  nsim_flags |= flags & O_RDONLY;
 | 
						|
  nsim_flags |= flags & O_WRONLY;
 | 
						|
  nsim_flags |= flags & O_RDWR;
 | 
						|
  nsim_flags |= (flags & O_CREAT) ? ARC_LINUX_CREAT : 0;
 | 
						|
  nsim_flags |= (flags & O_APPEND) ? ARC_LINUX_APPEND : 0;
 | 
						|
  nsim_flags |= (flags & O_TRUNC) ? ARC_LINUX_TRUNC : 0;
 | 
						|
  nsim_flags |= (flags & O_EXCL) ? ARC_LINUX_EXCL : 0;
 | 
						|
  /* There are other fcntl flags that are different between newlib and ARC
 | 
						|
     uClibc, however they are not supported by nSIM hostlink, therefore there
 | 
						|
     is no need to translate them.  */
 | 
						|
 | 
						|
  long __res;
 | 
						|
  _naked_syscall3 (__res, open, pathname, nsim_flags, mode)
 | 
						|
  return __res;
 | 
						|
}
 | 
						|
 | 
						|
/* Should be provided by crt0.S.  */
 | 
						|
extern void __attribute__((noreturn)) _exit_halt ();
 | 
						|
 | 
						|
void
 | 
						|
__attribute__((noreturn))
 | 
						|
_exit (int ret)
 | 
						|
{
 | 
						|
  /* Doing an "exit" system call would work on nSIM with hostlink, but call to
 | 
						|
     _exit_halt, which will do a CPU halt is more universal and will work in
 | 
						|
     many other cases as well, including an FPGA/SoC.  */
 | 
						|
  _exit_halt ();
 | 
						|
}
 | 
						|
 | 
						|
/* This is a copy of newlib/libc/posix/_isatty.c.  It is needed because nSIM
 | 
						|
   hostlink doesn't implement isatty system call.  Hardware boards on the other
 | 
						|
   hand would want isatty implementation that always returns 1, since they are
 | 
						|
   connected to console and doesn't have file IO.  */
 | 
						|
int
 | 
						|
_isatty (int fd)
 | 
						|
{
 | 
						|
  struct stat buf;
 | 
						|
 | 
						|
  if (fstat (fd, &buf) < 0)
 | 
						|
    {
 | 
						|
      errno = EBADF;
 | 
						|
      return 0;
 | 
						|
    }
 | 
						|
  if (S_ISCHR (buf.st_mode))
 | 
						|
    {
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
  errno = ENOTTY;
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
/* System call "getpid" is implemented in nSIM hostlink, but it is better not
 | 
						|
   to expose it in libgloss.  */
 | 
						|
int
 | 
						|
_getpid (void)
 | 
						|
{
 | 
						|
  return __MYPID;
 | 
						|
}
 | 
						|
 | 
						|
/* System call "kill" is implemented in nSIM hostlink on Linux hosts, but it
 | 
						|
   seems dangerous to expose it.  Instead, like most of the other "_kill"
 | 
						|
   implementations in libgloss, this will kill only self.  */
 | 
						|
int
 | 
						|
_kill (int pid, int sig)
 | 
						|
{
 | 
						|
  if (pid == __MYPID)
 | 
						|
    {
 | 
						|
      _exit (sig);
 | 
						|
    }
 | 
						|
  errno = ENOSYS;
 | 
						|
  return -1;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
translate_stat (struct nsim_stat *nsim, struct stat *buf)
 | 
						|
{
 | 
						|
  #define TR(field, type) buf->st_ ## field = (type) nsim->field
 | 
						|
  TR (dev, dev_t);
 | 
						|
  TR (ino, ino_t);
 | 
						|
  TR (mode, mode_t);
 | 
						|
  TR (nlink, nlink_t);
 | 
						|
  TR (uid, uid_t);
 | 
						|
  TR (gid, gid_t);
 | 
						|
  TR (rdev, dev_t);
 | 
						|
  TR (size, off_t);
 | 
						|
  TR (atime, time_t);
 | 
						|
  TR (mtime, time_t);
 | 
						|
  TR (ctime, time_t);
 | 
						|
  TR (blksize, long);
 | 
						|
  TR (blocks, long);
 | 
						|
  #undef TR
 | 
						|
}
 | 
						|
 | 
						|
/* stat/fstat implementation.  Situation is similiar to open and its flags -
 | 
						|
   structure is defined in libc, hence cannot be customized in libgloss, yet we
 | 
						|
   have a case where nSIM uses some definition which is not compatible with
 | 
						|
   neither old ARC-custom definition of "struct stat" in newlib, nor with
 | 
						|
   generic newlib implementation.  */
 | 
						|
int
 | 
						|
_stat (const char * path, struct stat *buf)
 | 
						|
{
 | 
						|
  struct nsim_stat nsim_stat;
 | 
						|
  long __res;
 | 
						|
  _naked_syscall2 (__res, stat, path, &nsim_stat)
 | 
						|
  translate_stat (&nsim_stat, buf);
 | 
						|
  return __res;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
_lstat (const char * path, struct stat *buf)
 | 
						|
{
 | 
						|
  struct nsim_stat nsim_stat;
 | 
						|
  long __res;
 | 
						|
  _naked_syscall2 (__res, stat, path, &nsim_stat)
 | 
						|
  translate_stat (&nsim_stat, buf);
 | 
						|
  return __res;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
_fstat (int fd, struct stat *buf)
 | 
						|
{
 | 
						|
  struct nsim_stat nsim_stat;
 | 
						|
  long __res;
 | 
						|
  _naked_syscall2 (__res, stat, fd, &nsim_stat)
 | 
						|
  translate_stat (&nsim_stat, buf);
 | 
						|
  return __res;
 | 
						|
}
 | 
						|
 | 
						|
/* Some system calls are implemented in nSIM hostlink, but are available only
 | 
						|
   on Linux hosts.  To minimize potential compatibility issues they are by
 | 
						|
   default disabled in libgloss build.  */
 | 
						|
#ifdef ARC_NSIM_WIN32_HOST
 | 
						|
_syscall3 (int, ioctl, int, fd, int, request, char *, argp)
 | 
						|
_syscall3 (_ssize_t, readv, int, fd, const struct iovec *, iov, int, iovcnt)
 | 
						|
_syscall3 (_ssize_t, writev, int, fd, const struct iovec *, iov, int, iovcnt)
 | 
						|
_syscall5 (off_t, llseek, int, fd, unsigned long, offset_high,
 | 
						|
	   unsigned long, offset_low, loff_t *, result,
 | 
						|
	   unsigned int, whence)
 | 
						|
_syscall2 (int, getrusage, int, who, struct rusage *, usage)
 | 
						|
_syscall2 (int, setrlimit, int, resource, const struct rlimit *, rlim)
 | 
						|
_syscall2 (int, getrlimit, int, resource, struct rlimit *, rlim)
 | 
						|
_syscall3 (int, sigaction, int signum, const struct sigaction *, act,
 | 
						|
	   struct sigaction *, oldact)
 | 
						|
_syscall0 (uid_t, getuid)
 | 
						|
_syscall0 (gid_t, getgid)
 | 
						|
_syscall0 (uid_t, geteuid)
 | 
						|
_syscall0 (gid_t, getegid)
 | 
						|
_syscall2 (int, kill, pid_t, pid, int, sig)
 | 
						|
_syscall3 (_ssize_t, readlink, const char *, path, char *, buf, size_t, bufsize)
 | 
						|
#endif
 |