diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 1d722c868..5ee12fc67 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -8,8 +8,13 @@ crtools-obj-y += crtools.o crtools-obj-y += cpu.o crtools-obj-y += prlimit.o +ifeq ($(ARCH),x86_64) SYS-DEF := syscall_64.tbl SYS-ASM-COMMON := syscall-common-x86-64.S +else +SYS-DEF := syscall_32.tbl +SYS-ASM-COMMON := syscall-common-x86-32.S +endif SYS-TYPES := ../../include/syscall-types.h SYS-CODES := ../../include/syscall-codes.h @@ -17,9 +22,19 @@ SYS-PROTO := ../../include/syscall.h SYS-EXEC-TBL := sys-exec-tbl.c +ifeq ($(ARCH),x86_64) syscalls-asm-y-asmflags := -fpie -Wstrict-prototypes -Wa,--noexecstack +else +syscalls-asm-y-asmflags := -fno-pic -Wstrict-prototypes -Wa,--noexecstack +endif syscalls-asm-y-asmflags += -nostdlib -fomit-frame-pointer -I$(obj) +ifneq ($(ARCH),x86_64) +syscalls-obj-y += syscalls/syscall32.o +$(obj)/syscalls/syscall32.o: $(obj)/$(SYS-CODES) $(obj)/$(SYS-PROTO) +endif +cleanup-y += $(obj)/syscalls/*.o $(obj)/syscalls/*.d + ASMFLAGS += -D__ASSEMBLY__ $(obj)/$(SYS-CODES): $(obj)/syscalls/$(SYS-DEF) @@ -39,6 +54,9 @@ $(obj)/$(SYS-PROTO): $(obj)/syscalls/$(SYS-DEF) $(Q) echo "#define __ASM_CR_SYSCALL_PROTO_H__" >> $@ $(Q) echo "#include \"syscall-codes.h\"" >> $@ $(Q) echo "#include \"syscall-types.h\"" >> $@ +ifneq ($(ARCH),x86_64) + $(Q) echo "#include \"asm/syscall32.h\"" >> $@ +endif $(Q) cat $< | awk '/^__NR/{print "extern long", $$3, substr($$0, index($$0,$$4)), ";"}' >> $@ $(Q) echo "#endif /* __ASM_CR_SYSCALL_PROTO_H__ */" >> $@ _all += $(obj)/$(SYS-PROTO) diff --git a/arch/x86/include/asm/syscall32.h b/arch/x86/include/asm/syscall32.h new file mode 100644 index 000000000..b0d5cb71d --- /dev/null +++ b/arch/x86/include/asm/syscall32.h @@ -0,0 +1,25 @@ +#ifndef __CR_SYSCALL32_H__ +#define __CR_SYSCALL32_H__ + +extern long sys_socket(int domain, int type, int protocol); +extern long sys_connect(int sockfd, struct sockaddr *addr, int addrlen); +extern long sys_sendto(int sockfd, void *buff, size_t len, unsigned int flags, struct sockaddr *addr, int addr_len); +extern long sys_recvfrom(int sockfd, void *ubuf, size_t size, unsigned int flags, struct sockaddr *addr, int *addr_len); +extern long sys_sendmsg(int sockfd, const struct msghdr *msg, int flags); +extern long sys_recvmsg(int sockfd, struct msghdr *msg, int flags); +extern long sys_shutdown(int sockfd, int how); +extern long sys_bind(int sockfd, const struct sockaddr *addr, int addrlen); +extern long sys_setsockopt(int sockfd, int level, int optname, const void *optval, unsigned int optlen); +extern long sys_getsockopt(int sockfd, int level, int optname, const void *optval, unsigned int *optlen); +extern long sys_shmat(int shmid, void *shmaddr, int shmflag); +extern long sys_pread(unsigned int fd, char *ubuf, u32 count, u64 pos); + +/* + * For x86_32 __NR_mmap inside the kernel represents old_mmap system + * call, but since we didn't use it yet lets go further and simply + * define own alias for __NR_mmap2 which would allow us to unify code + * between 32 and 64 bits version. + */ +#define __NR_mmap __NR_mmap2 + +#endif /* __CR_SYSCALL32_H__ */ diff --git a/arch/x86/syscalls/syscall-common-x86-32.S b/arch/x86/syscalls/syscall-common-x86-32.S new file mode 100644 index 000000000..ae6d594dc --- /dev/null +++ b/arch/x86/syscalls/syscall-common-x86-32.S @@ -0,0 +1,36 @@ +#include "asm/linkage.h" + +#define SYSCALL(name, opcode) \ + ENTRY(name); \ + movl $opcode, %eax; \ + jmp __syscall_common; \ + END(name) + +ENTRY(__syscall_common) + pushl %ebx + pushl %esi + pushl %edi + pushl %ebp + +#define __arg(n) (4 * (n) + 20)(%esp) + movl __arg(0),%ebx + movl __arg(1),%ecx + movl __arg(2),%edx + movl __arg(3),%esi + movl __arg(4),%edi + movl __arg(5),%ebp +#undef __arg + + int $0x80 + + popl %ebp + popl %edi + popl %esi + popl %ebx + ret +END(__syscall_common) + +ENTRY(__cr_restore_rt) + movl $__NR_rt_sigreturn, %eax + jmp __syscall_common +END(__cr_restore_rt) diff --git a/arch/x86/syscalls/syscall32.c b/arch/x86/syscalls/syscall32.c new file mode 100644 index 000000000..b68ef0957 --- /dev/null +++ b/arch/x86/syscalls/syscall32.c @@ -0,0 +1,85 @@ +#include "asm/types.h" +#include "syscall.h" + +#define SYS_SOCKET 1 /* sys_socket(2) */ +#define SYS_BIND 2 /* sys_bind(2) */ +#define SYS_CONNECT 3 /* sys_connect(2) */ +#define SYS_SENDTO 11 /* sys_sendto(2) */ +#define SYS_RECVFROM 12 /* sys_recvfrom(2) */ +#define SYS_SHUTDOWN 13 /* sys_shutdown(2) */ +#define SYS_SETSOCKOPT 14 /* sys_setsockopt(2) */ +#define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */ +#define SYS_SENDMSG 16 /* sys_sendmsg(2) */ +#define SYS_RECVMSG 17 /* sys_recvmsg(2) */ + +long sys_socket(int domain, int type, int protocol) +{ + u32 a[] = { (u32)domain, (u32)type, (u32)protocol }; + return sys_socketcall(SYS_SOCKET, (unsigned long *)a); +} + +long sys_connect(int sockfd, struct sockaddr *addr, int addrlen) +{ + u32 a[] = {(u32)sockfd, (u32)addr, (u32)addrlen}; + return sys_socketcall(SYS_CONNECT, (unsigned long *)a); +} + +long sys_sendto(int sockfd, void *buff, size_t len, unsigned int flags, struct sockaddr *addr, int addr_len) +{ + u32 a[] = {(u32)sockfd, (u32)buff, (u32)len, (u32)flags, (u32)addr, (u32)addr_len}; + return sys_socketcall(SYS_SENDTO, (unsigned long *)a); +} + +long sys_recvfrom(int sockfd, void *ubuf, size_t size, unsigned int flags, struct sockaddr *addr, int *addr_len) +{ + u32 a[] = {(u32)sockfd, (u32)ubuf, (u32)size, (u32)flags, (u32)addr, (u32)addr_len}; + return sys_socketcall(SYS_RECVFROM, (unsigned long *)a); +} + +long sys_sendmsg(int sockfd, const struct msghdr *msg, int flags) +{ + u32 a[] = {(u32)sockfd, (u32)msg, (u32)flags}; + return sys_socketcall(SYS_SENDMSG, (unsigned long *)a); +} + +long sys_recvmsg(int sockfd, struct msghdr *msg, int flags) +{ + u32 a[] = {(u32)sockfd, (u32)msg, (u32)flags}; + return sys_socketcall(SYS_RECVMSG, (unsigned long *)a); +} + +long sys_shutdown(int sockfd, int how) +{ + u32 a[] = {(u32)sockfd, (u32)how}; + return sys_socketcall(SYS_SHUTDOWN, (unsigned long *)a); +} + +long sys_bind(int sockfd, const struct sockaddr *addr, int addrlen) +{ + u32 a[] = {(u32)sockfd, (u32)addr, (u32)addrlen}; + return sys_socketcall(SYS_BIND, (unsigned long *)a); +} + +long sys_setsockopt(int sockfd, int level, int optname, const void *optval, unsigned int optlen) +{ + u32 a[] = {(u32)sockfd, (u32)level, (u32)optname, (u32)optval, (u32)optlen}; + return sys_socketcall(SYS_SETSOCKOPT, (unsigned long *)a); +} + +long sys_getsockopt(int sockfd, int level, int optname, const void *optval, unsigned int *optlen) +{ + u32 a[] = {(u32)sockfd, (u32)level, (u32)optname, (u32)optval, (u32)optlen}; + return sys_socketcall(SYS_GETSOCKOPT, (unsigned long *)a); +} + +#define SHMAT 21 + +long sys_shmat(int shmid, void *shmaddr, int shmflag) +{ + return sys_ipc(SHMAT, shmid, shmflag, 0, shmaddr, 0); +} + +long sys_pread(unsigned int fd, char *ubuf, u32 count, u64 pos) +{ + return sys_pread64(fd, ubuf, count, (u32)(pos & 0xffffffffu), (u32)(pos >> 32)); +} diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl new file mode 100644 index 000000000..0e0660774 --- /dev/null +++ b/arch/x86/syscalls/syscall_32.tbl @@ -0,0 +1,88 @@ +# +# System calls table, please make sure the table consist only the syscalls +# really used somewhere in project. +# +# code name arguments +# ------------------------------------------------------------------------------------------------------------------------------------------------------------- +__NR_restart_syscall 0 sys_restart_syscall (void) +__NR_exit 1 sys_exit (unsigned long error_code) +__NR_read 3 sys_read (int fd, void *buf, unsigned long count) +__NR_write 4 sys_write (int fd, const void *buf, unsigned long count) +__NR_open 5 sys_open (const char *filename, int flags, unsigned int mode) +__NR_close 6 sys_close (int fd) +__NR_unlink 10 sys_unlink (char *pathname) +__NR_lseek 19 sys_lseek (int fd, s32 offset, unsigned int origin) +__NR_getpid 20 sys_getpid (void) +__NR_mount 21 sys_mount (const char *dev_name, const char *dir_name, const char *type, unsigned long flags, const void *data) +__NR_kill 37 sys_kill (long pid, int sig) +__NR_mkdir 39 sys_mkdir (const char *name, int mode) +__NR_rmdir 40 sys_rmdir (const char *name) +__NR_brk 45 sys_brk (void *addr) +__NR_umount2 52 sys_umount2 (char *name, int flags) +__NR_ioctl 54 sys_ioctl (unsigned int fd, unsigned int cmd, unsigned long arg) +__NR_fcntl 55 sys_fcntl (unsigned int fd, unsigned int cmd, unsigned long arg) +__NR_umask 60 sys_umask (int mask) +__NR_setrlimit 75 sys_setrlimit (unsigned int resource, struct krlimit *rlim) +__NR_readlink 85 sys_readlink (const char *path, char *buf, int bufsize) +__NR_munmap 91 sys_munmap (void *addr, unsigned long len) +__NR_setpriority 97 sys_setpriority (int which, int who, int nice) +__NR_socketcall 102 sys_socketcall (int call, unsigned long *args) +__NR_setitimer 104 sys_setitimer (int which, struct itimerval *in, struct itimerval *out) +__NR_getitimer 105 sys_getitimer (int which, struct itimerval *it) +__NR_wait4 114 sys_wait4 (pid_t pid, int *stat_addr, int options, struct rusage *ru) +__NR_ipc 117 sys_ipc (unsigned int call, int first, unsigned long second, unsigned long third, void *ptr, long fifth) +__NR_clone 120 sys_clone (unsigned long flags, void *child_stack, void *parent_tid, void *child_tid) +__NR_mprotect 125 sys_mprotect (const void *addr, unsigned long len, unsigned long prot) +__NR_getpgid 132 sys_getpgid (pid_t pid) +__NR_personality 136 sys_personality (unsigned int personality) +__NR_flock 143 sys_flock (int fd, unsigned long cmd) +__NR_getsid 147 sys_getsid (void) +__NR_sched_setscheduler 156 sys_sched_setscheduler (int pid, int policy, struct sched_param *p) +__NR_nanosleep 162 sys_nanosleep (struct timespec *rqtp, struct timespec *rmtp) +__NR_mremap 163 sys_mremap (unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, unsigned long new_addr) +__NR_prctl 172 sys_prctl (int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) +__NR_rt_sigreturn 173 sys_rt_sigreturn (void) +__NR_rt_sigaction 174 sys_sigaction (int signum, const rt_sigaction_t *act, rt_sigaction_t *oldact, size_t sigsetsize) +__NR_rt_sigprocmask 175 sys_sigprocmask (int how, k_rtsigset_t *set, k_rtsigset_t *oset, size_t sigsetsize) +__NR_rt_sigqueueinfo 178 sys_rt_sigqueueinfo (pid_t pid, int sig, siginfo_t *uinfo) +__NR_pread64 180 sys_pread64 (unsigned int fd, char *ubuf, u32 count, u32 poslo, u32 poshi) +__NR_capget 184 sys_capget (struct cap_header *h, struct cap_data *d) +__NR_capset 185 sys_capset (struct cap_header *h, struct cap_data *d) +__NR_sigaltstack 186 sys_sigaltstack (const void *uss_ptr, void *uoss_ptr) +__NR_mmap2 192 sys_mmap (void *addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) +__NR_getgroups32 205 sys_getgroups (int gsize, unsigned int *groups) +__NR_setresuid32 208 sys_setresuid (int uid, int euid, int suid) +__NR_getresuid32 209 sys_getresuid (int *uid, int *euid, int *suid) +__NR_setresgid32 210 sys_setresgid (int gid, int egid, int sgid) +__NR_getresgid32 211 sys_getresgid (int *gid, int *egid, int *sgid) +__NR_setfsuid32 215 sys_setfsuid (int fsuid) +__NR_setfsgid32 216 sys_setfsgid (int fsgid) +__NR_mincore 218 sys_mincore (void *addr, unsigned long size, unsigned char *vec) +__NR_madvise 219 sys_madvise (unsigned long start, size_t len, int behavior) +__NR_gettid 224 sys_gettid (void) +__NR_futex 240 sys_futex (u32 *uaddr, int op, u32 val, struct timespec *utime, u32 *uaddr2, u32 val3) +__NR_set_thread_area 243 sys_set_thread_area (user_desc_t *info) +__NR_get_thread_area 244 sys_get_thread_area (user_desc_t *info) +__NR_io_setup 245 sys_io_setup (unsigned nr_reqs, aio_context_t *ctx32p) +__NR_io_getevents 247 sys_io_getevents (aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct timespec *timeout) +__NR_exit_group 252 sys_exit_group (int error_code) +__NR_set_tid_address 258 sys_set_tid_address (int *tid_addr) +__NR_timer_create 259 sys_timer_create (clockid_t which_clock, struct sigevent *timer_event_spec, timer_t *created_timer_id) +__NR_timer_settime 260 sys_timer_settime (timer_t timer_id, int flags, struct itimerspec *new, struct itimerspec *old) +__NR_timer_gettime 261 sys_timer_gettime (int timer_id, struct itimerspec *setting) +__NR_timer_getoverrun 262 sys_timer_getoverrun (int timer_id) +__NR_timer_delete 263 sys_timer_delete (timer_t timer_id) +__NR_clock_gettime 265 sys_clock_gettime (int which_clock, struct timespec *tp) +__NR_set_robust_list 311 sys_set_robust_list (struct robust_list_head *head, size_t len) +__NR_get_robust_list 312 sys_get_robust_list (int pid, struct robust_list_head **head_ptr, size_t *len_ptr) +__NR_vmsplice 316 sys_vmsplice (int fd, const struct iovec *iov, unsigned int nr_segs, unsigned int flags) +__NR_signalfd 321 sys_signalfd (int ufd, const k_rtsigset_t *sigmask, size_t sigsetsize) +__NR_timerfd_settime 325 sys_timerfd_settime (int ufd, int flags, const struct itimerspec *utmr, struct itimerspec *otmr) +__NR_rt_tgsigqueueinfo 335 sys_rt_tgsigqueueinfo (pid_t tgid, pid_t pid, int sig, siginfo_t *uinfo) +__NR_fanotify_init 338 sys_fanotify_init (unsigned int flags, unsigned int event_f_flags) +__NR_fanotify_mark 339 sys_fanotify_mark (int fanotify_fd, unsigned int flag, u32 mask, int dfd, const char *pathname) +__NR_prlimit64 340 sys_prlimit64 (pid_t pid, unsigned int resource, const struct rlimit64 *new_rlim, struct rlimit64 *old_rlim) +__NR_open_by_handle_at 342 sys_open_by_handle_at (int mountdirfd, struct file_handle *handle, int flags) +__NR_setns 346 sys_setns (int fd, int nstype) +__NR_kcmp 349 sys_kcmp (pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) +__NR_memfd_create 356 sys_memfd_create (const char *name, unsigned int flags)