From 28d5b98038dd18797375f4ff6a11fecd59809b22 Mon Sep 17 00:00:00 2001 From: Jim Wilson Date: Tue, 26 Dec 2017 12:27:52 -0800 Subject: [PATCH] RISC-V: Moved syscalls to separate files to fix aliasing problems. --- libgloss/riscv/Makefile.in | 35 ++- libgloss/riscv/internal_syscall.h | 52 ++++ libgloss/riscv/kernel_stat.h | 39 +++ libgloss/riscv/machine/syscall.h | 27 -- libgloss/riscv/sys_access.c | 9 + libgloss/riscv/sys_chdir.c | 8 + libgloss/riscv/sys_chmod.c | 9 + libgloss/riscv/sys_chown.c | 8 + libgloss/riscv/sys_close.c | 9 + libgloss/riscv/sys_conv_stat.c | 21 ++ libgloss/riscv/sys_execve.c | 11 + libgloss/riscv/sys_exit.c | 10 + libgloss/riscv/sys_faccessat.c | 8 + libgloss/riscv/sys_fork.c | 10 + libgloss/riscv/sys_fstat.c | 15 ++ libgloss/riscv/sys_fstatat.c | 14 + libgloss/riscv/sys_ftime.c | 10 + libgloss/riscv/sys_getcwd.c | 9 + libgloss/riscv/sys_getpid.c | 11 + libgloss/riscv/sys_gettimeofday.c | 10 + libgloss/riscv/sys_isatty.c | 17 ++ libgloss/riscv/sys_kill.c | 11 + libgloss/riscv/sys_link.c | 8 + libgloss/riscv/sys_lseek.c | 10 + libgloss/riscv/sys_lstat.c | 13 + libgloss/riscv/sys_open.c | 9 + libgloss/riscv/sys_openat.c | 8 + libgloss/riscv/sys_read.c | 9 + libgloss/riscv/sys_sbrk.c | 27 ++ libgloss/riscv/sys_stat.c | 14 + libgloss/riscv/sys_sysconf.c | 17 ++ libgloss/riscv/sys_times.c | 37 +++ libgloss/riscv/sys_unlink.c | 9 + libgloss/riscv/sys_utime.c | 8 + libgloss/riscv/sys_wait.c | 10 + libgloss/riscv/sys_write.c | 10 + libgloss/riscv/syscalls.c | 421 ------------------------------ 37 files changed, 513 insertions(+), 450 deletions(-) create mode 100644 libgloss/riscv/internal_syscall.h create mode 100644 libgloss/riscv/kernel_stat.h create mode 100644 libgloss/riscv/sys_access.c create mode 100644 libgloss/riscv/sys_chdir.c create mode 100644 libgloss/riscv/sys_chmod.c create mode 100644 libgloss/riscv/sys_chown.c create mode 100644 libgloss/riscv/sys_close.c create mode 100644 libgloss/riscv/sys_conv_stat.c create mode 100644 libgloss/riscv/sys_execve.c create mode 100644 libgloss/riscv/sys_exit.c create mode 100644 libgloss/riscv/sys_faccessat.c create mode 100644 libgloss/riscv/sys_fork.c create mode 100644 libgloss/riscv/sys_fstat.c create mode 100644 libgloss/riscv/sys_fstatat.c create mode 100644 libgloss/riscv/sys_ftime.c create mode 100644 libgloss/riscv/sys_getcwd.c create mode 100644 libgloss/riscv/sys_getpid.c create mode 100644 libgloss/riscv/sys_gettimeofday.c create mode 100644 libgloss/riscv/sys_isatty.c create mode 100644 libgloss/riscv/sys_kill.c create mode 100644 libgloss/riscv/sys_link.c create mode 100644 libgloss/riscv/sys_lseek.c create mode 100644 libgloss/riscv/sys_lstat.c create mode 100644 libgloss/riscv/sys_open.c create mode 100644 libgloss/riscv/sys_openat.c create mode 100644 libgloss/riscv/sys_read.c create mode 100644 libgloss/riscv/sys_sbrk.c create mode 100644 libgloss/riscv/sys_stat.c create mode 100644 libgloss/riscv/sys_sysconf.c create mode 100644 libgloss/riscv/sys_times.c create mode 100644 libgloss/riscv/sys_unlink.c create mode 100644 libgloss/riscv/sys_utime.c create mode 100644 libgloss/riscv/sys_wait.c create mode 100644 libgloss/riscv/sys_write.c delete mode 100644 libgloss/riscv/syscalls.c diff --git a/libgloss/riscv/Makefile.in b/libgloss/riscv/Makefile.in index de4ea8d83..503575975 100644 --- a/libgloss/riscv/Makefile.in +++ b/libgloss/riscv/Makefile.in @@ -6,8 +6,39 @@ gloss_hdrs = \ machine/syscall.h \ gloss_srcs = \ - syscalls.c \ - nanosleep.c + nanosleep.c \ + sys_access.c \ + sys_chdir.c \ + sys_chmod.c \ + sys_chown.c \ + sys_close.c \ + sys_conv_stat.c \ + sys_execve.c \ + sys_exit.c \ + sys_faccessat.c \ + sys_fork.c \ + sys_fstatat.c \ + sys_fstat.c \ + sys_ftime.c \ + sys_getcwd.c \ + sys_getpid.c \ + sys_gettimeofday.c \ + sys_isatty.c \ + sys_kill.c \ + sys_link.c \ + sys_lseek.c \ + sys_lstat.c \ + sys_openat.c \ + sys_open.c \ + sys_read.c \ + sys_sbrk.c \ + sys_stat.c \ + sys_sysconf.c \ + sys_times.c \ + sys_unlink.c \ + sys_utime.c \ + sys_wait.c \ + sys_write.c # Extra files diff --git a/libgloss/riscv/internal_syscall.h b/libgloss/riscv/internal_syscall.h new file mode 100644 index 000000000..8f7dcb451 --- /dev/null +++ b/libgloss/riscv/internal_syscall.h @@ -0,0 +1,52 @@ +/* Copyright (c) 2017 SiFive Inc. All rights reserved. + + This copyrighted material is made available to anyone wishing to use, + modify, copy, or redistribute it subject to the terms and conditions + of the FreeBSD License. This program is distributed in the hope that + it will be useful, but WITHOUT ANY WARRANTY expressed or implied, + including the implied warranties of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. A copy of this license is available at + http://www.opensource.org/licenses. +*/ + +#ifndef _INTERNAL_SYSCALL_H +#define _INTERNAL_SYSCALL_H + +#include + +static inline long +__syscall_error(long a0) +{ + errno = -a0; + return -1; +} + +static inline long +__internal_syscall(long n, long _a0, long _a1, long _a2, long _a3, long _a4, long _a5) +{ + register long a0 asm("a0") = _a0; + register long a1 asm("a1") = _a1; + register long a2 asm("a2") = _a2; + register long a3 asm("a3") = _a3; + register long a4 asm("a4") = _a4; + register long a5 asm("a5") = _a5; + +#ifdef __riscv_32e + register long syscall_id asm("t0") = n; +#else + register long syscall_id asm("a7") = n; +#endif + + asm volatile ("scall" + : "+r"(a0) : "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5), "r"(syscall_id)); + + if (a0 < 0) + return __syscall_error (a0); + else + return a0; +} + +#define syscall_errno(n, a, b, c, d, e, f) \ + __internal_syscall(n, (long)(a), (long)(b), (long)(c), (long)(d), (long)(e), (long)(f)) + +#endif diff --git a/libgloss/riscv/kernel_stat.h b/libgloss/riscv/kernel_stat.h new file mode 100644 index 000000000..d07bac544 --- /dev/null +++ b/libgloss/riscv/kernel_stat.h @@ -0,0 +1,39 @@ +/* Copyright (c) 2017 SiFive Inc. All rights reserved. + + This copyrighted material is made available to anyone wishing to use, + modify, copy, or redistribute it subject to the terms and conditions + of the FreeBSD License. This program is distributed in the hope that + it will be useful, but WITHOUT ANY WARRANTY expressed or implied, + including the implied warranties of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. A copy of this license is available at + http://www.opensource.org/licenses. +*/ + +#ifndef _RISCV_KERNEL_STAT_H +#define _RISCV_KERNEL_STAT_H + +#include +#include + +struct kernel_stat +{ + unsigned long long st_dev; + unsigned long long st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned int st_uid; + unsigned int st_gid; + unsigned long long st_rdev; + unsigned long long __pad1; + long long st_size; + int st_blksize; + int __pad2; + long long st_blocks; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + int __glibc_reserved[2]; +}; + +void _conv_stat (struct stat *, struct kernel_stat *); +#endif /* _RISCV_KERNEL_STAT_H */ diff --git a/libgloss/riscv/machine/syscall.h b/libgloss/riscv/machine/syscall.h index cc7183273..5cd15b848 100644 --- a/libgloss/riscv/machine/syscall.h +++ b/libgloss/riscv/machine/syscall.h @@ -54,31 +54,4 @@ #define SYS_time 1062 #define SYS_getmainvars 2011 -extern long __syscall_error(long); - -static inline long -__internal_syscall(long n, long _a0, long _a1, long _a2, long _a3, long _a4, long _a5) -{ - register long a0 asm("a0") = _a0; - register long a1 asm("a1") = _a1; - register long a2 asm("a2") = _a2; - register long a3 asm("a3") = _a3; - register long a4 asm("a4") = _a4; - register long a5 asm("a5") = _a5; - -#ifdef __riscv_32e - register long syscall_id asm("t0") = n; -#else - register long syscall_id asm("a7") = n; -#endif - - asm volatile ("scall" - : "+r"(a0) : "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5), "r"(syscall_id)); - - if (a0 < 0) - return __syscall_error (a0); - else - return a0; -} - #endif diff --git a/libgloss/riscv/sys_access.c b/libgloss/riscv/sys_access.c new file mode 100644 index 000000000..ef446d29b --- /dev/null +++ b/libgloss/riscv/sys_access.c @@ -0,0 +1,9 @@ +#include +#include "internal_syscall.h" + +/* Permissions of a file (by name). */ +int +_access(const char *file, int mode) +{ + return syscall_errno (SYS_access, file, mode, 0, 0, 0, 0); +} diff --git a/libgloss/riscv/sys_chdir.c b/libgloss/riscv/sys_chdir.c new file mode 100644 index 000000000..0b2b0f53d --- /dev/null +++ b/libgloss/riscv/sys_chdir.c @@ -0,0 +1,8 @@ +#include + +/* Stub. */ +int +_chdir(const char *path) +{ + return -1; +} diff --git a/libgloss/riscv/sys_chmod.c b/libgloss/riscv/sys_chmod.c new file mode 100644 index 000000000..2c11e1d03 --- /dev/null +++ b/libgloss/riscv/sys_chmod.c @@ -0,0 +1,9 @@ +#include +#include + +/* Stub. */ +int +_chmod(const char *path, mode_t mode) +{ + return -1; +} diff --git a/libgloss/riscv/sys_chown.c b/libgloss/riscv/sys_chown.c new file mode 100644 index 000000000..8faddffe2 --- /dev/null +++ b/libgloss/riscv/sys_chown.c @@ -0,0 +1,8 @@ +#include +#include + +/* Stub. */ +int _chown(const char *path, uid_t owner, gid_t group) +{ + return -1; +} diff --git a/libgloss/riscv/sys_close.c b/libgloss/riscv/sys_close.c new file mode 100644 index 000000000..80b10c66a --- /dev/null +++ b/libgloss/riscv/sys_close.c @@ -0,0 +1,9 @@ +#include +#include "internal_syscall.h" + +/* Close a file. */ +int +_close(int file) +{ + return syscall_errno (SYS_close, file, 0, 0, 0, 0, 0); +} diff --git a/libgloss/riscv/sys_conv_stat.c b/libgloss/riscv/sys_conv_stat.c new file mode 100644 index 000000000..73c6a8672 --- /dev/null +++ b/libgloss/riscv/sys_conv_stat.c @@ -0,0 +1,21 @@ +#include +#include "kernel_stat.h" + +/* Convert linux's stat64 sturct to newlib's stat. */ +void +_conv_stat (struct stat *st, struct kernel_stat *kst) +{ + st->st_dev = kst->st_dev; + st->st_ino = kst->st_ino; + st->st_mode = kst->st_mode; + st->st_nlink = kst->st_nlink; + st->st_uid = kst->st_uid; + st->st_gid = kst->st_gid; + st->st_rdev = kst->st_rdev; + st->st_size = kst->st_size; + st->st_blocks = kst->st_blocks; + st->st_blksize = kst->st_blksize; + st->st_atime = kst->st_atim.tv_sec; + st->st_mtime = kst->st_mtim.tv_sec; + st->st_ctime = kst->st_ctim.tv_sec; +} diff --git a/libgloss/riscv/sys_execve.c b/libgloss/riscv/sys_execve.c new file mode 100644 index 000000000..d6447373e --- /dev/null +++ b/libgloss/riscv/sys_execve.c @@ -0,0 +1,11 @@ +#include +#include "internal_syscall.h" + +/* Transfer control to a new process. Minimal implementation for a + system without processes from newlib documentation. */ +int +_execve(const char *name, char *const argv[], char *const env[]) +{ + errno = ENOMEM; + return -1; +} diff --git a/libgloss/riscv/sys_exit.c b/libgloss/riscv/sys_exit.c new file mode 100644 index 000000000..03e1c34e8 --- /dev/null +++ b/libgloss/riscv/sys_exit.c @@ -0,0 +1,10 @@ +#include +#include "internal_syscall.h" + +/* Exit a program without cleaning up files. */ +void +_exit(int exit_status) +{ + syscall_errno (SYS_exit, exit_status, 0, 0, 0, 0, 0); + while (1); +} diff --git a/libgloss/riscv/sys_faccessat.c b/libgloss/riscv/sys_faccessat.c new file mode 100644 index 000000000..e966a4a78 --- /dev/null +++ b/libgloss/riscv/sys_faccessat.c @@ -0,0 +1,8 @@ +#include +#include "internal_syscall.h" + +/* Permissions of a file (by name) in a given directory. */ +int _faccessat(int dirfd, const char *file, int mode, int flags) +{ + return syscall_errno (SYS_faccessat, dirfd, file, mode, flags, 0, 0); +} diff --git a/libgloss/riscv/sys_fork.c b/libgloss/riscv/sys_fork.c new file mode 100644 index 000000000..8ace14096 --- /dev/null +++ b/libgloss/riscv/sys_fork.c @@ -0,0 +1,10 @@ +#include +#include "internal_syscall.h" + +/* Create a new process. Minimal implementation for a system without + processes from newlib documentation. */ +int _fork() +{ + errno = EAGAIN; + return -1; +} diff --git a/libgloss/riscv/sys_fstat.c b/libgloss/riscv/sys_fstat.c new file mode 100644 index 000000000..13a0bca2f --- /dev/null +++ b/libgloss/riscv/sys_fstat.c @@ -0,0 +1,15 @@ +#include +#include "kernel_stat.h" +#include "internal_syscall.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) +{ + struct kernel_stat kst; + int rv = syscall_errno (SYS_fstat, file, &kst, 0, 0, 0, 0); + _conv_stat (st, &kst); + return rv; +} diff --git a/libgloss/riscv/sys_fstatat.c b/libgloss/riscv/sys_fstatat.c new file mode 100644 index 000000000..0e4ea42d0 --- /dev/null +++ b/libgloss/riscv/sys_fstatat.c @@ -0,0 +1,14 @@ +#include +#include "kernel_stat.h" +#include "internal_syscall.h" + +/* Status of an open file. The sys/stat.h header file required is + distributed in the include subdirectory for this C library. */ +int +_fstatat(int dirfd, const char *file, struct stat *st, int flags) +{ + struct kernel_stat kst; + int rv = syscall_errno (SYS_fstatat, dirfd, file, &kst, flags, 0, 0); + _conv_stat (st, &kst); + return rv; +} diff --git a/libgloss/riscv/sys_ftime.c b/libgloss/riscv/sys_ftime.c new file mode 100644 index 000000000..5705592be --- /dev/null +++ b/libgloss/riscv/sys_ftime.c @@ -0,0 +1,10 @@ +#include +#include + +/* Get the current time. Only relatively correct. */ +int +_ftime(struct timeb *tp) +{ + tp->time = tp->millitm = 0; + return 0; +} diff --git a/libgloss/riscv/sys_getcwd.c b/libgloss/riscv/sys_getcwd.c new file mode 100644 index 000000000..b0fb205d7 --- /dev/null +++ b/libgloss/riscv/sys_getcwd.c @@ -0,0 +1,9 @@ +#include +#include + +/* Stub. */ +char * +_getcwd(char *buf, size_t size) +{ + return NULL; +} diff --git a/libgloss/riscv/sys_getpid.c b/libgloss/riscv/sys_getpid.c new file mode 100644 index 000000000..2aa072177 --- /dev/null +++ b/libgloss/riscv/sys_getpid.c @@ -0,0 +1,11 @@ +#include + +/* Get process id. This is sometimes used to generate strings unlikely + to conflict with other processes. Minimal implementation for a + system without processes just returns 1. */ + +int +_getpid() +{ + return 1; +} diff --git a/libgloss/riscv/sys_gettimeofday.c b/libgloss/riscv/sys_gettimeofday.c new file mode 100644 index 000000000..457dcbcc7 --- /dev/null +++ b/libgloss/riscv/sys_gettimeofday.c @@ -0,0 +1,10 @@ +#include +#include +#include "internal_syscall.h" + +/* Get the current time. Only relatively correct. */ +int +_gettimeofday(struct timeval *tp, void *tzp) +{ + return syscall_errno (SYS_gettimeofday, tp, 0, 0, 0, 0, 0); +} diff --git a/libgloss/riscv/sys_isatty.c b/libgloss/riscv/sys_isatty.c new file mode 100644 index 000000000..0dc3db169 --- /dev/null +++ b/libgloss/riscv/sys_isatty.c @@ -0,0 +1,17 @@ +#include +#include +#include "internal_syscall.h" + +extern int _fstat(int file, struct stat *st); + +/* Query whether output stream is a terminal. For consistency with the + other minimal implementations, which only support output to stdout, + this minimal implementation is suggested by the newlib docs. */ + +int +_isatty(int file) +{ + struct stat s; + int ret = _fstat (file, &s); + return ret == -1 ? -1 : !!(s.st_mode & S_IFCHR); +} diff --git a/libgloss/riscv/sys_kill.c b/libgloss/riscv/sys_kill.c new file mode 100644 index 000000000..cf7f224ef --- /dev/null +++ b/libgloss/riscv/sys_kill.c @@ -0,0 +1,11 @@ +#include +#include "internal_syscall.h" + +/* Send a signal. Minimal implementation for a system without processes + just causes an error. */ +int +_kill(int pid, int sig) +{ + errno = EINVAL; + return -1; +} diff --git a/libgloss/riscv/sys_link.c b/libgloss/riscv/sys_link.c new file mode 100644 index 000000000..eaeb22b25 --- /dev/null +++ b/libgloss/riscv/sys_link.c @@ -0,0 +1,8 @@ +#include +#include "internal_syscall.h" + +/* Establish a new name for an existing file. */ +int _link(const char *old_name, const char *new_name) +{ + return syscall_errno (SYS_link, old_name, new_name, 0, 0, 0, 0); +} diff --git a/libgloss/riscv/sys_lseek.c b/libgloss/riscv/sys_lseek.c new file mode 100644 index 000000000..7486a3a3e --- /dev/null +++ b/libgloss/riscv/sys_lseek.c @@ -0,0 +1,10 @@ +#include +#include +#include "internal_syscall.h" + +/* Set position in a file. */ +off_t +_lseek(int file, off_t ptr, int dir) +{ + return syscall_errno (SYS_lseek, file, ptr, dir, 0, 0, 0); +} diff --git a/libgloss/riscv/sys_lstat.c b/libgloss/riscv/sys_lstat.c new file mode 100644 index 000000000..2eeabcce3 --- /dev/null +++ b/libgloss/riscv/sys_lstat.c @@ -0,0 +1,13 @@ +#include +#include +#include "internal_syscall.h" +#include "kernel_stat.h" + +/* Status of a link (by name). */ +int _lstat(const char *file, struct stat *st) +{ + struct kernel_stat kst; + int rv = syscall_errno (SYS_lstat, file, &kst, 0, 0, 0, 0); + _conv_stat (st, &kst); + return rv; +} diff --git a/libgloss/riscv/sys_open.c b/libgloss/riscv/sys_open.c new file mode 100644 index 000000000..4fd5d672f --- /dev/null +++ b/libgloss/riscv/sys_open.c @@ -0,0 +1,9 @@ +#include +#include "internal_syscall.h" + +/* Open a file. */ +int +_open(const char *name, int flags, int mode) +{ + return syscall_errno (SYS_open, name, flags, mode, 0, 0, 0); +} diff --git a/libgloss/riscv/sys_openat.c b/libgloss/riscv/sys_openat.c new file mode 100644 index 000000000..cf429b7b2 --- /dev/null +++ b/libgloss/riscv/sys_openat.c @@ -0,0 +1,8 @@ +#include +#include "internal_syscall.h" + +/* Open file relative to given directory. */ +int _openat(int dirfd, const char *name, int flags, int mode) +{ + return syscall_errno (SYS_openat, dirfd, name, flags, mode, 0, 0); +} diff --git a/libgloss/riscv/sys_read.c b/libgloss/riscv/sys_read.c new file mode 100644 index 000000000..7367e2643 --- /dev/null +++ b/libgloss/riscv/sys_read.c @@ -0,0 +1,9 @@ +#include +#include +#include "internal_syscall.h" + +/* Read from a file. */ +ssize_t _read(int file, void *ptr, size_t len) +{ + return syscall_errno (SYS_read, file, ptr, len, 0, 0, 0); +} diff --git a/libgloss/riscv/sys_sbrk.c b/libgloss/riscv/sys_sbrk.c new file mode 100644 index 000000000..036b897f4 --- /dev/null +++ b/libgloss/riscv/sys_sbrk.c @@ -0,0 +1,27 @@ +#include +#include +#include "internal_syscall.h" + +/* Increase program data space. As malloc and related functions depend + on this, it is useful to have a working implementation. The following + is suggested by the newlib docs and suffices for a standalone + system. */ +void * +_sbrk(ptrdiff_t incr) +{ + static unsigned long heap_end; + + if (heap_end == 0) + { + long brk = syscall_errno (SYS_brk, 0, 0, 0, 0, 0, 0); + if (brk == -1) + return (void *)-1; + heap_end = brk; + } + + if (syscall_errno (SYS_brk, heap_end + incr, 0, 0, 0, 0, 0) != heap_end + incr) + return (void *)-1; + + heap_end += incr; + return (void *)(heap_end - incr); +} diff --git a/libgloss/riscv/sys_stat.c b/libgloss/riscv/sys_stat.c new file mode 100644 index 000000000..a193b10ad --- /dev/null +++ b/libgloss/riscv/sys_stat.c @@ -0,0 +1,14 @@ +#include +#include "kernel_stat.h" +#include "internal_syscall.h" + +/* Status of a file (by name). */ + +int +_stat(const char *file, struct stat *st) +{ + struct kernel_stat kst; + int rv = syscall_errno (SYS_stat, file, &kst, 0, 0, 0, 0); + _conv_stat (st, &kst); + return rv; +} diff --git a/libgloss/riscv/sys_sysconf.c b/libgloss/riscv/sys_sysconf.c new file mode 100644 index 000000000..dffdebab9 --- /dev/null +++ b/libgloss/riscv/sys_sysconf.c @@ -0,0 +1,17 @@ +#include +#include +#include + +/* Get configurable system variables. */ + +long +_sysconf(int name) +{ + switch (name) + { + case _SC_CLK_TCK: + return CLOCKS_PER_SEC; + } + + return -1; +} diff --git a/libgloss/riscv/sys_times.c b/libgloss/riscv/sys_times.c new file mode 100644 index 000000000..eb0ef9d1f --- /dev/null +++ b/libgloss/riscv/sys_times.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include "internal_syscall.h" + +extern int _gettimeofday(struct timeval *, void *); + +/* Timing information for current process. From + newlib/libc/include/sys/times.h the tms struct fields are as follows: + + - clock_t tms_utime : user clock ticks + - clock_t tms_stime : system clock ticks + - clock_t tms_cutime : children's user clock ticks + - clock_t tms_cstime : children's system clock ticks + + Since maven does not currently support processes we set both of the + children's times to zero. Eventually we might want to separately + account for user vs system time, but for now we just return the total + number of cycles since starting the program. */ +clock_t +_times(struct tms *buf) +{ + // when called for the first time, initialize t0 + static struct timeval t0; + if (t0.tv_sec == 0) + _gettimeofday (&t0, 0); + + struct timeval t; + _gettimeofday (&t, 0); + + long long utime = (t.tv_sec - t0.tv_sec) * 1000000 + (t.tv_usec - t0.tv_usec); + buf->tms_utime = utime * CLOCKS_PER_SEC / 1000000; + buf->tms_stime = buf->tms_cstime = buf->tms_cutime = 0; + + return -1; +} diff --git a/libgloss/riscv/sys_unlink.c b/libgloss/riscv/sys_unlink.c new file mode 100644 index 000000000..b55fe1ec2 --- /dev/null +++ b/libgloss/riscv/sys_unlink.c @@ -0,0 +1,9 @@ +#include +#include "internal_syscall.h" + +/* Remove a file's directory entry. */ +int +_unlink(const char *name) +{ + return syscall_errno (SYS_unlink, name, 0, 0, 0, 0, 0); +} diff --git a/libgloss/riscv/sys_utime.c b/libgloss/riscv/sys_utime.c new file mode 100644 index 000000000..c03a968e4 --- /dev/null +++ b/libgloss/riscv/sys_utime.c @@ -0,0 +1,8 @@ +#include + +/* Stub. */ +int +_utime(const char *path, const struct utimbuf *times) +{ + return -1; +} diff --git a/libgloss/riscv/sys_wait.c b/libgloss/riscv/sys_wait.c new file mode 100644 index 000000000..25bf44800 --- /dev/null +++ b/libgloss/riscv/sys_wait.c @@ -0,0 +1,10 @@ +#include +#include + +/* Wait for a child process. Minimal implementation for a system without + processes just causes an error. */ +int _wait(int *status) +{ + errno = ECHILD; + return -1; +} diff --git a/libgloss/riscv/sys_write.c b/libgloss/riscv/sys_write.c new file mode 100644 index 000000000..b972734e2 --- /dev/null +++ b/libgloss/riscv/sys_write.c @@ -0,0 +1,10 @@ +#include +#include +#include "internal_syscall.h" + +/* Write to a file. */ +ssize_t +_write(int file, const void *ptr, size_t len) +{ + return syscall_errno (SYS_write, file, ptr, len, 0, 0, 0); +} diff --git a/libgloss/riscv/syscalls.c b/libgloss/riscv/syscalls.c deleted file mode 100644 index 19c69f083..000000000 --- a/libgloss/riscv/syscalls.c +++ /dev/null @@ -1,421 +0,0 @@ -/* Copyright (c) 2017 SiFive Inc. All rights reserved. - - This copyrighted material is made available to anyone wishing to use, - modify, copy, or redistribute it subject to the terms and conditions - of the FreeBSD License. This program is distributed in the hope that - it will be useful, but WITHOUT ANY WARRANTY expressed or implied, - including the implied warranties of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. A copy of this license is available at - http://www.opensource.org/licenses. - - ======================================================================== - syscalls.c : Newlib operating system interface - ======================================================================== - This is the maven implementation of the narrow newlib operating - system interface. It is based on the minimum stubs in the newlib - documentation, the error stubs in libnosys, and the previous scale - implementation. Please do not include any additional system calls or - other functions in this file. Additional header and source files - should be in the machine subdirectory. - - Here is a list of the functions which make up the operating system - interface. The file management instructions execute syscall assembly - instructions so that a proxy kernel (or the simulator) can marshal up - the request to the host machine. The process management functions are - mainly just stubs since for now maven only supports a single process. - - - File management functions - + open : (v) open file - + lseek : (v) set position in file - + read : (v) read from file - + write : (v) write to file - + fstat : (z) status of an open file - + stat : (z) status of a file by name - + close : (z) close a file - + link : (z) rename a file - + unlink : (z) remote file's directory entry - - - Process management functions - + execve : (z) transfer control to new proc - + fork : (z) create a new process - + getpid : (v) get process id - + kill : (z) send signal to child process - + wait : (z) wait for a child process - - - Misc functions - + isatty : (v) query whether output stream is a terminal - + times : (z) timing information for current process - + sbrk : (v) increase program data space - + _exit : (-) exit program without cleaning up files - - There are two types of system calls. Those which return a value when - everything is okay (marked with (v) in above list) and those which - return a zero when everything is okay (marked with (z) in above - list). On an error (ie. when the error flag is 1) the return value is - always an errno which should correspond to the numbers in - newlib/libc/include/sys/errno.h - - See the newlib documentation for more information - http://sourceware.org/newlib/libc.html#Syscalls -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define syscall_errno(n, a, b, c, d, e, f) \ - __internal_syscall(n, (long)(a), (long)(b), (long)(c), \ - (long)(d), (long)(e), (long)(f)) - -long -__syscall_error(long a0) -{ - errno = -a0; - return -1; -} - -/* Open a file. */ -int -_open(const char *name, int flags, int mode) -{ - return syscall_errno (SYS_open, name, flags, mode, 0, 0, 0); -} - -/* Open file relative to given directory. */ -int -_openat(int dirfd, const char *name, int flags, int mode) -{ - return syscall_errno (SYS_openat, dirfd, name, flags, mode, 0, 0); -} - -/* Set position in a file. */ -off_t -_lseek(int file, off_t ptr, int dir) -{ - return syscall_errno (SYS_lseek, file, ptr, dir, 0, 0, 0); -} - -/* Read from a file. */ -ssize_t -_read(int file, void *ptr, size_t len) -{ - return syscall_errno (SYS_read, file, ptr, len, 0, 0, 0); -} - -/* Write to a file. */ -ssize_t -_write(int file, const void *ptr, size_t len) -{ - return syscall_errno (SYS_write, file, ptr, len, 0, 0, 0); -} - -struct kernel_stat -{ - unsigned long long st_dev; - unsigned long long st_ino; - unsigned int st_mode; - unsigned int st_nlink; - unsigned int st_uid; - unsigned int st_gid; - unsigned long long st_rdev; - unsigned long long __pad1; - long long st_size; - int st_blksize; - int __pad2; - long long st_blocks; - struct timespec st_atim; - struct timespec st_mtim; - struct timespec st_ctim; - int __glibc_reserved[2]; -}; - -/* Convert linux's stat64 sturct to newlib's stat. */ -static void -conv_stat (struct stat *st, struct kernel_stat *kst) -{ - st->st_dev = kst->st_dev; - st->st_ino = kst->st_ino; - st->st_mode = kst->st_mode; - st->st_nlink = kst->st_nlink; - st->st_uid = kst->st_uid; - st->st_gid = kst->st_gid; - st->st_rdev = kst->st_rdev; - st->st_size = kst->st_size; - st->st_blocks = kst->st_blocks; - st->st_blksize = kst->st_blksize; - st->st_atime = kst->st_atim.tv_sec; - st->st_mtime = kst->st_mtim.tv_sec; - st->st_ctime = kst->st_ctim.tv_sec; -} - -/* 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) -{ - struct kernel_stat kst; - int rv = syscall_errno (SYS_fstat, file, &kst, 0, 0, 0, 0); - conv_stat (st, &kst); - return rv; -} - -/* Status of a file (by name). */ -int -_stat(const char *file, struct stat *st) -{ - struct kernel_stat kst; - int rv = syscall_errno (SYS_stat, file, &kst, 0, 0, 0, 0); - conv_stat (st, &kst); - return rv; -} - -/* Status of a link (by name). */ -int -_lstat(const char *file, struct stat *st) -{ - struct kernel_stat kst; - int rv = syscall_errno (SYS_lstat, file, &kst, 0, 0, 0, 0); - conv_stat (st, &kst); - return rv; -} - -/* Status of a file (by name) in a given directory. */ -int -_fstatat(int dirfd, const char *file, struct stat *st, int flags) -{ - struct kernel_stat kst; - int rv = syscall_errno (SYS_fstatat, dirfd, file, &kst, flags, 0, 0); - conv_stat (st, &kst); - return rv; -} - -/* Permissions of a file (by name). */ -int -_access(const char *file, int mode) -{ - return syscall_errno (SYS_access, file, mode, 0, 0, 0, 0); -} - -/* Permissions of a file (by name) in a given directory. */ -int -_faccessat(int dirfd, const char *file, int mode, int flags) -{ - return syscall_errno (SYS_faccessat, dirfd, file, mode, flags, 0, 0); -} - -/* Close a file. */ -int -_close(int file) -{ - return syscall_errno (SYS_close, file, 0, 0, 0, 0, 0); -} - -/* Establish a new name for an existing file. */ -int -_link(const char *old_name, const char *new_name) -{ - return syscall_errno (SYS_link, old_name, new_name, 0, 0, 0, 0); -} - -/* Remove a file's directory entry. */ -int -_unlink(const char *name) -{ - return syscall_errno (SYS_unlink, name, 0, 0, 0, 0, 0); -} - -/* Transfer control to a new process. Minimal implementation for a - system without processes from newlib documentation. */ -int -_execve(const char *name, char *const argv[], char *const env[]) -{ - errno = ENOMEM; - return -1; -} - -/* Create a new process. Minimal implementation for a system without - processes from newlib documentation. */ - -int -_fork() -{ - errno = EAGAIN; - return -1; -} - -/* Get process id. This is sometimes used to generate strings unlikely - to conflict with other processes. Minimal implementation for a - system without processes just returns 1. */ - -int -_getpid() -{ - return 1; -} - -/* Send a signal. Minimal implementation for a system without processes - just causes an error. */ - -int -_kill(int pid, int sig) -{ - errno = EINVAL; - return -1; -} - -/* Wait for a child process. Minimal implementation for a system without - processes just causes an error. */ - -int -_wait(int *status) -{ - errno = ECHILD; - return -1; -} - -/* Query whether output stream is a terminal. For consistency with the - other minimal implementations, which only support output to stdout, - this minimal implementation is suggested by the newlib docs. */ - -int -_isatty(int file) -{ - struct stat s; - int ret = _fstat (file, &s); - return ret == -1 ? -1 : !!(s.st_mode & S_IFCHR); -} - -/* Get the current time. Only relatively correct. */ - -int -_gettimeofday(struct timeval *tp, void *tz) -{ - return syscall_errno (SYS_gettimeofday, tp, 0, 0, 0, 0, 0); -} - -/* Timing information for current process. From - newlib/libc/include/sys/times.h the tms struct fields are as follows: - - - clock_t tms_utime : user clock ticks - - clock_t tms_stime : system clock ticks - - clock_t tms_cutime : children's user clock ticks - - clock_t tms_cstime : children's system clock ticks - - Since maven does not currently support processes we set both of the - children's times to zero. Eventually we might want to separately - account for user vs system time, but for now we just return the total - number of cycles since starting the program. */ -clock_t -_times(struct tms *buf) -{ - // when called for the first time, initialize t0 - static struct timeval t0; - if(t0.tv_sec == 0) - _gettimeofday (&t0,0); - - struct timeval t; - _gettimeofday (&t, 0); - - long long utime = (t.tv_sec - t0.tv_sec) * 1000000 + (t.tv_usec - t0.tv_usec); - buf->tms_utime = utime * CLOCKS_PER_SEC / 1000000; - buf->tms_stime = buf->tms_cstime = buf->tms_cutime = 0; - - return -1; -} - -/* Get the current time. Only relatively correct. */ -int -_ftime(struct timeb *tp) -{ - tp->time = tp->millitm = 0; - return 0; -} - -/* Stub. */ -int -_utime(const char *path, const struct utimbuf *times) -{ - return -1; -} - -/* Stub. */ -int -_chown(const char *path, uid_t owner, gid_t group) -{ - return -1; -} - -/* Stub. */ -int -_chmod(const char *path, mode_t mode) -{ - return -1; -} - -/* Stub. */ -int -_chdir(const char *path) -{ - return -1; -} - -/* Stub. */ -char * -_getcwd(char *buf, size_t size) -{ - return NULL; -} - -/* Get configurable system variables. */ - -long -_sysconf(int name) -{ - switch (name) - { - case _SC_CLK_TCK: - return CLOCKS_PER_SEC; - } - - return -1; -} - -/* Increase program data space. As malloc and related functions depend - on this, it is useful to have a working implementation. The following - is suggested by the newlib docs and suffices for a standalone - system. */ -void * -_sbrk(ptrdiff_t incr) -{ - static unsigned long heap_end; - - if (heap_end == 0) - { - long brk = syscall_errno (SYS_brk, 0, 0, 0, 0, 0, 0); - if (brk == -1) - return (void *)-1; - heap_end = brk; - } - - if (syscall_errno (SYS_brk, heap_end + incr, 0, 0, 0, 0, 0) - != heap_end + incr) - return (void *)-1; - - heap_end += incr; - return (void *)(heap_end - incr); -} - -/* Exit a program without cleaning up files. */ - -void -_exit(int exit_status) -{ - syscall_errno (SYS_exit, exit_status, 0, 0, 0, 0, 0); - while (1); -}