From a48f11d0af793110f1a5289967bcb45a188058c3 Mon Sep 17 00:00:00 2001 From: swcompiler Date: Fri, 29 Nov 2024 14:04:40 +0800 Subject: [PATCH 07/23] Sw64: Linux Syscall Interface --- sysdeps/unix/sw_64/Makefile | 4 + sysdeps/unix/sw_64/pipe.S | 31 ++ sysdeps/unix/sw_64/rt-sysdep.S | 1 + sysdeps/unix/sw_64/sysdep.S | 65 ++++ sysdeps/unix/sysv/linux/sw_64/arch-syscall.h | 376 +++++++++++++++++++ sysdeps/unix/sysv/linux/sw_64/clone.S | 117 ++++++ sysdeps/unix/sysv/linux/sw_64/syscall.S | 70 ++++ sysdeps/unix/sysv/linux/sw_64/sysdep.h | 355 +++++++++++++++++ sysdeps/unix/sysv/linux/sw_64/vfork.S | 41 ++ 9 files changed, 1060 insertions(+) create mode 100644 sysdeps/unix/sw_64/Makefile create mode 100644 sysdeps/unix/sw_64/pipe.S create mode 100644 sysdeps/unix/sw_64/rt-sysdep.S create mode 100644 sysdeps/unix/sw_64/sysdep.S create mode 100644 sysdeps/unix/sysv/linux/sw_64/arch-syscall.h create mode 100644 sysdeps/unix/sysv/linux/sw_64/clone.S create mode 100644 sysdeps/unix/sysv/linux/sw_64/syscall.S create mode 100644 sysdeps/unix/sysv/linux/sw_64/sysdep.h create mode 100644 sysdeps/unix/sysv/linux/sw_64/vfork.S diff --git a/sysdeps/unix/sw_64/Makefile b/sysdeps/unix/sw_64/Makefile new file mode 100644 index 00000000..0660847f --- /dev/null +++ b/sysdeps/unix/sw_64/Makefile @@ -0,0 +1,4 @@ +ifeq ($(subdir),rt) +librt-sysdep_routines += rt-sysdep +librt-shared-only-routines += rt-sysdep +endif diff --git a/sysdeps/unix/sw_64/pipe.S b/sysdeps/unix/sw_64/pipe.S new file mode 100644 index 00000000..d851fe17 --- /dev/null +++ b/sysdeps/unix/sw_64/pipe.S @@ -0,0 +1,31 @@ +/* Copyright (C) 1993-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger (davidm@cs.arizona.edu). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +/* __pipe is a special syscall since it returns two values. */ + +#include + +PSEUDO (__pipe, pipe, 0) + stw r0, 0(a0) + stw r1, 4(a0) + mov zero, v0 + ret +PSEUDO_END(__pipe) + +libc_hidden_def (__pipe) +weak_alias (__pipe, pipe) diff --git a/sysdeps/unix/sw_64/rt-sysdep.S b/sysdeps/unix/sw_64/rt-sysdep.S new file mode 100644 index 00000000..f966bf1e --- /dev/null +++ b/sysdeps/unix/sw_64/rt-sysdep.S @@ -0,0 +1 @@ +#include diff --git a/sysdeps/unix/sw_64/sysdep.S b/sysdeps/unix/sw_64/sysdep.S new file mode 100644 index 00000000..306184c3 --- /dev/null +++ b/sysdeps/unix/sw_64/sysdep.S @@ -0,0 +1,65 @@ +/* Copyright (C) 1993-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Brendan Kehoe (brendan@zen.org). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +#include +#include + +#if defined(PIC) + /* Put this at the end of libc's text segment so that all of + the direct branches from the syscalls are forward, and + thus predicted not taken. */ + .section .text.last, "ax", @progbits +#else + .text +#endif + +#if IS_IN (libc) +# define SYSCALL_ERROR_ERRNO __libc_errno +#else +# define SYSCALL_ERROR_ERRNO errno +#endif + + .align 4 + .globl __syscall_error + .ent __syscall_error +__syscall_error: + /* When building a shared library, we branch here without having + loaded the GP. Nor, since it was a direct branch, have we + loaded PV with our address. + + When building a static library, we tail call here from another + object file, possibly with a different GP, and must return with + the GP of our caller in place so that linker relaxation works. + + Both issues are solved by computing the GP into T1 instead of + clobbering the traditional GP register. */ + .prologue 0 + mov v0, t0 + br t1, 1f +1: ldih t1, 0(t1) !gpdisp!1 + sys_call HMC_rdunique + + ldi t1, 0(t1) !gpdisp!1 + ldl t1, SYSCALL_ERROR_ERRNO(t1) !gottprel + addl v0, t1, t1 + ldi v0, -1 + + stw t0, 0(t1) + ret + + .end __syscall_error diff --git a/sysdeps/unix/sysv/linux/sw_64/arch-syscall.h b/sysdeps/unix/sysv/linux/sw_64/arch-syscall.h new file mode 100644 index 00000000..62597a14 --- /dev/null +++ b/sysdeps/unix/sysv/linux/sw_64/arch-syscall.h @@ -0,0 +1,376 @@ +/* AUTOGENERATED by update-syscall-lists.py. */ +#define __NR_accept 99 +#define __NR_accept4 502 +#define __NR_access 33 +#define __NR_acct 51 +#define __NR_add_key 439 +#define __NR_adjtimex 366 +#define __NR_afs_syscall 338 +#define __NR_bdflush 300 +#define __NR_bind 104 +#define __NR_bpf 170 +#define __NR_brk 17 +#define __NR_cachestat 190 +#define __NR_capget 368 +#define __NR_capset 369 +#define __NR_chdir 12 +#define __NR_chmod 15 +#define __NR_chown 16 +#define __NR_chroot 61 +#define __NR_clock_adjtime 499 +#define __NR_clock_getres 421 +#define __NR_clock_gettime 420 +#define __NR_clock_nanosleep 422 +#define __NR_clock_settime 419 +#define __NR_clone 312 +#define __NR_clone3 282 +#define __NR_close 6 +#define __NR_close_range 283 +#define __NR_connect 98 +#define __NR_copy_file_range 515 +#define __NR_create_module 306 +#define __NR_delete_module 308 +#define __NR_dipc 373 +#define __NR_dup 41 +#define __NR_dup2 90 +#define __NR_dup3 487 +#define __NR_epoll_create 407 +#define __NR_epoll_create1 486 +#define __NR_epoll_ctl 408 +#define __NR_epoll_pwait 474 +#define __NR_epoll_pwait2 180 +#define __NR_epoll_wait 409 +#define __NR_eventfd 478 +#define __NR_eventfd2 485 +#define __NR_execve 59 +#define __NR_execveat 513 +#define __NR_exit 1 +#define __NR_exit_group 405 +#define __NR_faccessat 462 +#define __NR_faccessat2 286 +#define __NR_fadvise64 413 +#define __NR_fallocate 480 +#define __NR_fanotify_init 494 +#define __NR_fanotify_mark 495 +#define __NR_fchdir 13 +#define __NR_fchmod 124 +#define __NR_fchmodat 461 +#define __NR_fchmodat2 191 +#define __NR_fchown 123 +#define __NR_fchownat 453 +#define __NR_fcntl 92 +#define __NR_fdatasync 447 +#define __NR_fgetxattr 387 +#define __NR_finit_module 507 +#define __NR_flistxattr 390 +#define __NR_flock 131 +#define __NR_fork 2 +#define __NR_fremovexattr 393 +#define __NR_fsconfig 278 +#define __NR_fsetxattr 384 +#define __NR_fsmount 279 +#define __NR_fsopen 277 +#define __NR_fspick 280 +#define __NR_fstat 91 +#define __NR_fstat64 427 +#define __NR_fstatat64 455 +#define __NR_fstatfs 329 +#define __NR_fstatfs64 230 +#define __NR_fsync 95 +#define __NR_ftruncate 130 +#define __NR_futex 394 +#define __NR_futex_waitv 188 +#define __NR_futimesat 454 +#define __NR_get_kernel_syms 309 +#define __NR_get_mempolicy 430 +#define __NR_get_robust_list 467 +#define __NR_getcpu 473 +#define __NR_getcwd 367 +#define __NR_getdents 305 +#define __NR_getdents64 377 +#define __NR_getegid 179 +#define __NR_geteuid 177 +#define __NR_getgid 178 +#define __NR_getgroups 79 +#define __NR_gethostname 87 +#define __NR_getitimer 361 +#define __NR_getpeername 141 +#define __NR_getpgid 233 +#define __NR_getpgrp 63 +#define __NR_getpid 174 +#define __NR_getppid 175 +#define __NR_getpriority 298 +#define __NR_getrandom 511 +#define __NR_getresgid 372 +#define __NR_getresuid 344 +#define __NR_getrlimit 144 +#define __NR_getrusage 364 +#define __NR_getsid 234 +#define __NR_getsockname 150 +#define __NR_getsockopt 118 +#define __NR_getsysinfo 256 +#define __NR_gettid 378 +#define __NR_gettimeofday 359 +#define __NR_getuid 176 +#define __NR_getxattr 385 +#define __NR_getxgid 47 +#define __NR_getxpid 20 +#define __NR_getxuid 24 +#define __NR_init_module 307 +#define __NR_inotify_add_watch 445 +#define __NR_inotify_init 444 +#define __NR_inotify_init1 489 +#define __NR_inotify_rm_watch 446 +#define __NR_io_cancel 402 +#define __NR_io_destroy 399 +#define __NR_io_getevents 400 +#define __NR_io_pgetevents 403 +#define __NR_io_setup 398 +#define __NR_io_submit 401 +#define __NR_io_uring_enter 273 +#define __NR_io_uring_register 274 +#define __NR_io_uring_setup 272 +#define __NR_ioctl 54 +#define __NR_ioprio_get 443 +#define __NR_ioprio_set 442 +#define __NR_kcmp 506 +#define __NR_kexec_load 448 +#define __NR_keyctl 441 +#define __NR_kill 37 +#define __NR_landlock_add_rule 184 +#define __NR_landlock_create_ruleset 183 +#define __NR_landlock_restrict_self 185 +#define __NR_lchown 208 +#define __NR_lgetxattr 386 +#define __NR_link 9 +#define __NR_linkat 458 +#define __NR_listen 106 +#define __NR_listxattr 388 +#define __NR_llistxattr 389 +#define __NR_lookup_dcookie 406 +#define __NR_lremovexattr 392 +#define __NR_lseek 19 +#define __NR_lsetxattr 383 +#define __NR_lstat 68 +#define __NR_lstat64 426 +#define __NR_madvise 75 +#define __NR_mbind 429 +#define __NR_membarrier 172 +#define __NR_memfd_create 512 +#define __NR_migrate_pages 449 +#define __NR_mincore 375 +#define __NR_mkdir 136 +#define __NR_mkdirat 451 +#define __NR_mknod 14 +#define __NR_mknodat 452 +#define __NR_mlock 314 +#define __NR_mlock2 173 +#define __NR_mlockall 316 +#define __NR_mmap 71 +#define __NR_mount 302 +#define __NR_mount_setattr 181 +#define __NR_move_mount 276 +#define __NR_move_pages 472 +#define __NR_mprotect 74 +#define __NR_mq_getsetattr 437 +#define __NR_mq_notify 436 +#define __NR_mq_open 432 +#define __NR_mq_timedreceive 435 +#define __NR_mq_timedsend 434 +#define __NR_mq_unlink 433 +#define __NR_mremap 341 +#define __NR_msgctl 200 +#define __NR_msgget 201 +#define __NR_msgrcv 202 +#define __NR_msgsnd 203 +#define __NR_msync 217 +#define __NR_munlock 315 +#define __NR_munlockall 317 +#define __NR_munmap 73 +#define __NR_name_to_handle_at 497 +#define __NR_nanosleep 340 +#define __NR_nfsservctl 342 +#define __NR_odd_getpriority 100 +#define __NR_odd_sigprocmask 48 +#define __NR_oldumount 321 +#define __NR_open 45 +#define __NR_open_by_handle_at 498 +#define __NR_open_tree 275 +#define __NR_openat 450 +#define __NR_openat2 284 +#define __NR_pciconfig_iobase 376 +#define __NR_pciconfig_read 345 +#define __NR_pciconfig_write 346 +#define __NR_perf_event_open 493 +#define __NR_personality 324 +#define __NR_pidfd_getfd 285 +#define __NR_pidfd_open 281 +#define __NR_pidfd_send_signal 271 +#define __NR_pipe 42 +#define __NR_pipe2 488 +#define __NR_pivot_root 374 +#define __NR_pkey_alloc 289 +#define __NR_pkey_free 290 +#define __NR_pkey_mprotect 288 +#define __NR_poll 94 +#define __NR_ppoll 464 +#define __NR_prctl 348 +#define __NR_pread64 349 +#define __NR_preadv 490 +#define __NR_preadv2 516 +#define __NR_prlimit64 496 +#define __NR_process_madvise 287 +#define __NR_process_mrelease 187 +#define __NR_process_vm_readv 504 +#define __NR_process_vm_writev 505 +#define __NR_pselect6 463 +#define __NR_ptrace 26 +#define __NR_pwrite64 350 +#define __NR_pwritev 491 +#define __NR_pwritev2 517 +#define __NR_query_module 347 +#define __NR_quotactl 148 +#define __NR_quotactl_fd 182 +#define __NR_read 3 +#define __NR_readahead 379 +#define __NR_readlink 58 +#define __NR_readlinkat 460 +#define __NR_readv 120 +#define __NR_reboot 311 +#define __NR_recv 102 +#define __NR_recvfrom 125 +#define __NR_recvmmsg 479 +#define __NR_recvmsg 113 +#define __NR_remap_file_pages 410 +#define __NR_removexattr 391 +#define __NR_rename 128 +#define __NR_renameat 457 +#define __NR_renameat2 510 +#define __NR_request_key 440 +#define __NR_restart_syscall 412 +#define __NR_rmdir 137 +#define __NR_rseq 404 +#define __NR_rt_sigaction 352 +#define __NR_rt_sigpending 354 +#define __NR_rt_sigprocmask 353 +#define __NR_rt_sigqueueinfo 356 +#define __NR_rt_sigreturn 351 +#define __NR_rt_sigsuspend 357 +#define __NR_rt_sigtimedwait 355 +#define __NR_rt_tgsigqueueinfo 492 +#define __NR_sched_get_priority_max 335 +#define __NR_sched_get_priority_min 336 +#define __NR_sched_getaffinity 396 +#define __NR_sched_getattr 509 +#define __NR_sched_getparam 331 +#define __NR_sched_getscheduler 333 +#define __NR_sched_rr_get_interval 337 +#define __NR_sched_setaffinity 395 +#define __NR_sched_setattr 508 +#define __NR_sched_setparam 330 +#define __NR_sched_setscheduler 332 +#define __NR_sched_yield 334 +#define __NR_seccomp 514 +#define __NR_select 358 +#define __NR_semctl 204 +#define __NR_semget 205 +#define __NR_semop 206 +#define __NR_semtimedop 423 +#define __NR_send 101 +#define __NR_sendfile 370 +#define __NR_sendmmsg 503 +#define __NR_sendmsg 114 +#define __NR_sendto 133 +#define __NR_set_mempolicy 431 +#define __NR_set_mempolicy_home_node 189 +#define __NR_set_robust_list 466 +#define __NR_set_tid_address 411 +#define __NR_setdomainname 166 +#define __NR_setfsgid 326 +#define __NR_setfsuid 325 +#define __NR_setgid 132 +#define __NR_setgroups 80 +#define __NR_sethostname 88 +#define __NR_setitimer 362 +#define __NR_setns 501 +#define __NR_setpgid 39 +#define __NR_setpgrp 82 +#define __NR_setpriority 96 +#define __NR_setregid 127 +#define __NR_setresgid 371 +#define __NR_setresuid 343 +#define __NR_setreuid 126 +#define __NR_setrlimit 145 +#define __NR_setsid 147 +#define __NR_setsockopt 105 +#define __NR_setsysinfo 257 +#define __NR_settimeofday 360 +#define __NR_setuid 23 +#define __NR_setxattr 382 +#define __NR_shmat 209 +#define __NR_shmctl 210 +#define __NR_shmdt 211 +#define __NR_shmget 212 +#define __NR_shutdown 134 +#define __NR_sigaction 156 +#define __NR_sigaltstack 235 +#define __NR_signalfd 476 +#define __NR_signalfd4 484 +#define __NR_sigpending 52 +#define __NR_sigprocmask 299 +#define __NR_sigreturn 103 +#define __NR_sigsuspend 111 +#define __NR_socket 97 +#define __NR_socketcall 119 +#define __NR_socketpair 135 +#define __NR_splice 468 +#define __NR_stat 67 +#define __NR_stat64 425 +#define __NR_statfs 328 +#define __NR_statfs64 229 +#define __NR_statx 518 +#define __NR_swapoff 304 +#define __NR_swapon 322 +#define __NR_symlink 57 +#define __NR_symlinkat 459 +#define __NR_sync 36 +#define __NR_sync_file_range 469 +#define __NR_syncfs 500 +#define __NR_sysfs 254 +#define __NR_sysinfo 318 +#define __NR_syslog 310 +#define __NR_tee 470 +#define __NR_tgkill 424 +#define __NR_timer_create 414 +#define __NR_timer_delete 418 +#define __NR_timer_getoverrun 417 +#define __NR_timer_gettime 416 +#define __NR_timer_settime 415 +#define __NR_timerfd 477 +#define __NR_timerfd_create 481 +#define __NR_timerfd_gettime 483 +#define __NR_timerfd_settime 482 +#define __NR_times 323 +#define __NR_tkill 381 +#define __NR_truncate 129 +#define __NR_tuxcall 397 +#define __NR_umask 60 +#define __NR_umount 22 +#define __NR_umount2 22 +#define __NR_uname 339 +#define __NR_unlink 10 +#define __NR_unlinkat 456 +#define __NR_unshare 465 +#define __NR_uselib 313 +#define __NR_userfaultfd 171 +#define __NR_ustat 327 +#define __NR_utimensat 475 +#define __NR_utimes 363 +#define __NR_vfork 66 +#define __NR_vhangup 76 +#define __NR_vmsplice 471 +#define __NR_vserver 428 +#define __NR_wait4 365 +#define __NR_waitid 438 +#define __NR_write 4 +#define __NR_writev 121 diff --git a/sysdeps/unix/sysv/linux/sw_64/clone.S b/sysdeps/unix/sysv/linux/sw_64/clone.S new file mode 100644 index 00000000..6f08adae --- /dev/null +++ b/sysdeps/unix/sysv/linux/sw_64/clone.S @@ -0,0 +1,117 @@ +/* Copyright (C) 1996-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#include +#define _ERRNO_H 1 +#include + +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, + void *arg, pid_t *ptid, void *tls, pid_t *ctid); + + Note that everything past ARG is technically optional, based + on FLAGS, and that CTID is arg 7, and thus is on the stack. + However, since a load from top-of-stack better be legal always, + we don't bother checking FLAGS. */ + + .text + .align 4 + .globl __clone + .ent __clone + .usepv __clone, USEPV_PROF + + cfi_startproc +__clone: +#ifdef PROF + .set noat + ldgp gp,0(pv) + ldi AT, _mcount + call AT, (AT), _mcount + .set at +#endif + + /* Sanity check arguments. */ + ldi v0, EINVAL + beq a0, SYSCALL_ERROR_LABEL /* no NULL function pointers */ + bic a1, 0xf,a1 /*Align sp. By zyl */ + beq a1, SYSCALL_ERROR_LABEL /* no NULL stack pointers */ + + /* Save the fn ptr and arg on the new stack. */ + subl a1, 32, a1 + stl a0, 0(a1) + stl a3, 8(a1) + stl a2, 16(a1) + + /* The syscall is of the form clone(flags, usp, ptid, ctid, tls). + Shift the flags, ptid, ctid, tls arguments into place; the + child_stack argument is already correct. */ + mov a2, a0 + mov a4, a2 + ldl a3, 0(sp) + mov a5, a4 + + /* Do the system call. */ + ldi v0, __NR_clone + sys_call HMC_callsys + + bne a3, SYSCALL_ERROR_LABEL + beq v0, thread_start + + /* Successful return from the parent. */ + ret + +PSEUDO_END(__clone) + cfi_endproc + +/* Load up the arguments to the function. Put this block of code in + its own function so that we can terminate the stack trace with our + debug info. */ + + .align 4 + .ent thread_start + cfi_startproc +thread_start: + mov 0, fp + cfi_def_cfa_register(fp) + cfi_undefined(ra) + + /* Load up the arguments. */ + ldl pv, 0(sp) + ldl a0, 8(sp) + addl sp, 32, sp + + /* Call the user's function. */ + call ra, (pv) + ldgp gp, 0(ra) + + mov v0, a0 + ldi v0, __NR_exit + sys_call HMC_callsys + + /* Die horribly. */ + .align 4 + halt + + .align 4 + cfi_endproc + .end thread_start + +libc_hidden_def (__clone) +weak_alias (__clone, clone) diff --git a/sysdeps/unix/sysv/linux/sw_64/syscall.S b/sysdeps/unix/sysv/linux/sw_64/syscall.S new file mode 100644 index 00000000..286b9925 --- /dev/null +++ b/sysdeps/unix/sysv/linux/sw_64/syscall.S @@ -0,0 +1,70 @@ +/* Copyright (C) 1996-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +#include + +/* + * This is for COMPATIBILITY with Linux/x86 only. Linux/Sw_64 system + * calls return an error indication in a3. This allows arbitrary 64bit + * values to be returned in v0 (because negative values are not + * mistaken as error numbers). However, C allows only one value to + * be returned, so the interface below foflds the error indication passed in + * a3 back into v0: it sets v0 to -errno if an error occurs. Thus, + * no negative 64bit numbers can be returned. To avoid this problem, + * use assembly stubs wherever possible/convenient. + * + * Usage: + * + * long syscall(syscall_number, arg1, arg2, arg3, arg4, arg5, arg6) + * + * syscall_number = the index of the system call we're invoking + * arg1-arg6 = up to 6 integer arguments to the system call + * + * We need to do some arg shifting: the kernel expects the + * syscall number in v0 and the first six args in a0-a5. + * + */ + + +LEAF(__syscall, 0) +#ifdef PROF + ldgp gp, 0(pv) + .set noat + ldi AT, _mcount + call AT, (AT), _mcount + .set at + .prologue 1 +#else + .prologue 0 +#endif + + mov a0, v0 /* Syscall number -> v0 */ + mov a1, a0 /* arg1-arg5 -> a0-a4 */ + mov a2, a1 + mov a3, a2 + mov a4, a3 + mov a5, a4 + ldl a5,0(sp) /* arg6 -> a5 */ + + sys_call HMC_callsys /* Invoke system call */ + bne a3, SYSCALL_ERROR_LABEL + ret + +PSEUDO_END(__syscall) + +weak_alias (__syscall, syscall) diff --git a/sysdeps/unix/sysv/linux/sw_64/sysdep.h b/sysdeps/unix/sysv/linux/sw_64/sysdep.h new file mode 100644 index 00000000..f047c609 --- /dev/null +++ b/sysdeps/unix/sysv/linux/sw_64/sysdep.h @@ -0,0 +1,355 @@ +/* Copyright (C) 1992-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper, , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +#ifndef _LINUX_SW_64_SYSDEP_H +#define _LINUX_SW_64_SYSDEP_H 1 + +/* There is some commonality. */ +#include +#include +#include /* Defines RTLD_PRIVATE_ERRNO. */ + +#include + +/* For Linux we can use the system call table in the header file + /usr/include/asm/unistd.h + of the kernel. But these symbols do not follow the SYS_* syntax + so we have to redefine the `SYS_ify' macro here. */ +#undef SYS_ify +#define SYS_ify(syscall_name) __NR_##syscall_name + +#define SINGLE_THREAD_BY_GLOBAL 1 + +#ifdef __ASSEMBLER__ +# include +# include + +# define __LABEL(x) x##: + +# define LEAF(name, framesize) \ + .globl name; \ + .align 4; \ + .ent name, 0; \ + __LABEL (name).frame sp, framesize, ra + +# define ENTRY(name) \ + .globl name; \ + .align 4; \ + .ent name, 0; \ + __LABEL (name).frame sp, 0, ra + +/* Mark the end of function SYM. */ +# undef END +# define END(sym) .end sym + +# ifdef PROF +# define PSEUDO_PROF \ + .set noat; \ + ldi AT, _mcount; \ + call AT, (AT), _mcount; \ + .set at +# else +# define PSEUDO_PROF +# endif + +# ifdef PROF +# define PSEUDO_PROLOGUE \ + .frame sp, 0, ra; \ + ldgp gp, 0(pv); \ + PSEUDO_PROF; \ + .prologue 1 +# elif defined PIC +# define PSEUDO_PROLOGUE \ + .frame sp, 0, ra; \ + .prologue 0 +# else +# define PSEUDO_PROLOGUE \ + .frame sp, 0, ra; \ + ldgp gp, 0(pv); \ + .prologue 1 +# endif /* PROF */ + +# ifdef PROF +# define USEPV_PROF std +# else +# define USEPV_PROF no +# endif + +# undef SYSCALL_ERROR_LABEL +# if RTLD_PRIVATE_ERRNO +# define SYSCALL_ERROR_LABEL $syscall_error +# define SYSCALL_ERROR_HANDLER \ + $syscall_error: \ + stw v0, rtld_errno (gp) !gprel; \ + ldi v0, -1; \ + ret +# define SYSCALL_ERROR_FALLTHRU +# elif defined(PIC) +# define SYSCALL_ERROR_LABEL __syscall_error !samegp +# define SYSCALL_ERROR_HANDLER +# define SYSCALL_ERROR_FALLTHRU br SYSCALL_ERROR_LABEL +# else +# define SYSCALL_ERROR_LABEL $syscall_error +# define SYSCALL_ERROR_HANDLER \ + $syscall_error: \ + jmp $31, __syscall_error +# define SYSCALL_ERROR_FALLTHRU +# endif /* RTLD_PRIVATE_ERRNO */ + +/* Overridden by specific syscalls. */ +# undef PSEUDO_PREPARE_ARGS +# define PSEUDO_PREPARE_ARGS /* Nothing. */ + +# define PSEUDO(name, syscall_name, args) \ + .globl name; \ + .align 4; \ + .ent name, 0; \ + __LABEL (name) \ + PSEUDO_PROLOGUE; \ + PSEUDO_PREPARE_ARGS \ + ldi v0, SYS_ify (syscall_name); \ + sys_call HMC_callsys; \ + bne a3, SYSCALL_ERROR_LABEL + +# undef PSEUDO_END +# define PSEUDO_END(sym) \ + SYSCALL_ERROR_HANDLER; \ + END (sym) + +# define PSEUDO_NOERRNO(name, syscall_name, args) \ + .globl name; \ + .align 4; \ + .ent name, 0; \ + __LABEL (name) \ + PSEUDO_PROLOGUE; \ + PSEUDO_PREPARE_ARGS \ + ldi v0, SYS_ify (syscall_name); \ + sys_call HMC_callsys; + +# undef PSEUDO_END_NOERRNO +# define PSEUDO_END_NOERRNO(sym) END (sym) + +# define ret_NOERRNO ret + +# define PSEUDO_ERRVAL(name, syscall_name, args) \ + .globl name; \ + .align 4; \ + .ent name, 0; \ + __LABEL (name) \ + PSEUDO_PROLOGUE; \ + PSEUDO_PREPARE_ARGS \ + ldi v0, SYS_ify (syscall_name); \ + sys_call HMC_callsys; + +# undef PSEUDO_END_ERRVAL +# define PSEUDO_END_ERRVAL(sym) END (sym) + +# define ret_ERRVAL ret + +# define r0 v0 +# define r1 a4 + +# define MOVE(x, y) mov x, y + +#else /* !ASSEMBLER */ + +#define HAVE_CLOCK_GETTIME_VSYSCALL "__vdso_clock_gettime" +#define HAVE_CLOCK_GETTIME64_VSYSCALL "__vdso_clock_gettime64" + +#define INTERNAL_SYSCALL(name, nr, args...) \ + internal_syscall##nr(__NR_##name, args) + +# define INTERNAL_SYSCALL_NCS(name, nr, args...) \ + internal_syscall##nr (name, args) + +/* The normal Sw_64 calling convention sign-extends 32-bit quantties + no matter what the "real" sign of the 32-bit type. We want to + preserve that when filling in values for the kernel. */ +# define syscall_promote(arg) \ + (sizeof (arg) == 4 ? (long int) (int) (long int) (arg) : (long int) (arg)) + +# define internal_syscall_clobbers \ + "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$22", "$23", "$24", \ + "$25", "$27", "$28", "memory" + +/* It is moderately important optimization-wise to limit the lifetime + of the hard-register variables as much as possible. Thus we copy + in/out as close to the asm as possible. */ + +# define internal_syscall0(name, args...) \ + ({ \ + register long int _sc_19 __asm__("$19"); \ + register long int _sc_0 = name; \ + __asm__ __volatile__("sys_call 0x83 # %0 %1 <= %2" \ + : "+v"(_sc_0), "=r"(_sc_19) \ + : \ + : internal_syscall_clobbers, "$16", "$17", "$18", \ + "$20", "$21"); \ + _sc_19 != 0 ? -_sc_0 : _sc_0; \ + }) + +# define internal_syscall1(name, arg1) \ + ({ \ + register long int _tmp_16 = syscall_promote (arg1); \ + register long int _sc_0 = name; \ + register long int _sc_16 __asm__("$16") = _tmp_16; \ + register long int _sc_19 __asm__("$19"); \ + __asm__ __volatile__("sys_call 0x83 # %0 %1 <= %2 %3" \ + : "+v"(_sc_0), "=r"(_sc_19), "+r"(_sc_16) \ + : \ + : internal_syscall_clobbers, "$17", "$18", "$20", \ + "$21"); \ + _sc_19 != 0 ? -_sc_0 : _sc_0; \ + }) + +# define internal_syscall2(name, arg1, arg2) \ + ({ \ + register long int _tmp_16 = syscall_promote (arg1); \ + register long int _tmp_17 = syscall_promote (arg2); \ + register long int _sc_0 = name; \ + register long int _sc_16 __asm__("$16") = _tmp_16; \ + register long int _sc_17 __asm__("$17") = _tmp_17; \ + register long int _sc_19 __asm__("$19"); \ + __asm__ __volatile__("sys_call 0x83 # %0 %1 <= %2 %3 %4" \ + : "+v"(_sc_0), "=r"(_sc_19), "+r"(_sc_16), \ + "+r"(_sc_17) \ + : \ + : internal_syscall_clobbers, "$18", "$20", "$21"); \ + _sc_19 != 0 ? -_sc_0 : _sc_0; \ + }) + +# define internal_syscall3(name, arg1, arg2, arg3) \ + ({ \ + register long int _tmp_16 = syscall_promote (arg1); \ + register long int _tmp_17 = syscall_promote (arg2); \ + register long int _tmp_18 = syscall_promote (arg3); \ + register long int _sc_0 = name; \ + register long int _sc_16 __asm__("$16") = _tmp_16; \ + register long int _sc_17 __asm__("$17") = _tmp_17; \ + register long int _sc_18 __asm__("$18") = _tmp_18; \ + register long int _sc_19 __asm__("$19"); \ + __asm__ __volatile__("sys_call 0x83 # %0 %1 <= %2 %3 %4 %5" \ + : "+v"(_sc_0), "=r"(_sc_19), "+r"(_sc_16), \ + "+r"(_sc_17), "+r"(_sc_18) \ + : \ + : internal_syscall_clobbers, "$20", "$21"); \ + _sc_19 != 0 ? -_sc_0 : _sc_0; \ + }) + +# define internal_syscall4(name, arg1, arg2, arg3, arg4) \ + ({ \ + register long int _tmp_16 = syscall_promote (arg1); \ + register long int _tmp_17 = syscall_promote (arg2); \ + register long int _tmp_18 = syscall_promote (arg3); \ + register long int _tmp_19 = syscall_promote (arg4); \ + register long int _sc_0 = name; \ + register long int _sc_16 __asm__("$16") = _tmp_16; \ + register long int _sc_17 __asm__("$17") = _tmp_17; \ + register long int _sc_18 __asm__("$18") = _tmp_18; \ + register long int _sc_19 __asm__("$19") = _tmp_19; \ + __asm__ __volatile__("sys_call 0x83 # %0 %1 <= %2 %3 %4 %5 %6" \ + : "+v"(_sc_0), "+r"(_sc_19), "+r"(_sc_16), \ + "+r"(_sc_17), "+r"(_sc_18) \ + : \ + : internal_syscall_clobbers, "$20", "$21"); \ + _sc_19 != 0 ? -_sc_0 : _sc_0; \ + }) + +# define internal_syscall5(name, arg1, arg2, arg3, arg4, arg5) \ + ({ \ + register long int _tmp_16 = syscall_promote (arg1); \ + register long int _tmp_17 = syscall_promote (arg2); \ + register long int _tmp_18 = syscall_promote (arg3); \ + register long int _tmp_19 = syscall_promote (arg4); \ + register long int _tmp_20 = syscall_promote (arg5); \ + register long int _sc_0 = name; \ + register long int _sc_16 __asm__("$16") = _tmp_16; \ + register long int _sc_17 __asm__("$17") = _tmp_17; \ + register long int _sc_18 __asm__("$18") = _tmp_18; \ + register long int _sc_19 __asm__("$19") = _tmp_19; \ + register long int _sc_20 __asm__("$20") = _tmp_20; \ + __asm__ __volatile__("sys_call 0x83 # %0 %1 <= %2 %3 %4 %5 %6 %7" \ + : "+v"(_sc_0), "+r"(_sc_19), "+r"(_sc_16), \ + "+r"(_sc_17), "+r"(_sc_18), "+r"(_sc_20) \ + : \ + : internal_syscall_clobbers, "$21"); \ + _sc_19 != 0 ? -_sc_0 : _sc_0; \ + }) + +# define internal_syscall6(name, arg1, arg2, arg3, arg4, arg5, arg6) \ + ({ \ + register long int _tmp_16 = syscall_promote (arg1); \ + register long int _tmp_17 = syscall_promote (arg2); \ + register long int _tmp_18 = syscall_promote (arg3); \ + register long int _tmp_19 = syscall_promote (arg4); \ + register long int _tmp_20 = syscall_promote (arg5); \ + register long int _tmp_21 = syscall_promote (arg6); \ + register long int _sc_0 = name; \ + register long int _sc_16 __asm__("$16") = _tmp_16; \ + register long int _sc_17 __asm__("$17") = _tmp_17; \ + register long int _sc_18 __asm__("$18") = _tmp_18; \ + register long int _sc_19 __asm__("$19") = _tmp_19; \ + register long int _sc_20 __asm__("$20") = _tmp_20; \ + register long int _sc_21 __asm__("$21") = _tmp_21; \ + __asm__ __volatile__("sys_call 0x83 # %0 %1 <= %2 %3 %4 %5 %6 %7 %8" \ + : "+v"(_sc_0), "+r"(_sc_19), "+r"(_sc_16), \ + "+r"(_sc_17), "+r"(_sc_18), "+r"(_sc_20), \ + "+r"(_sc_21) \ + : \ + : internal_syscall_clobbers); \ + _sc_19 != 0 ? -_sc_0 : _sc_0; \ + }) +#endif /* ASSEMBLER */ + +/* Pointer mangling support. Note that tls access is slow enough that + we don't deoptimize things by placing the pointer check value there. */ + +#ifdef __ASSEMBLER__ +# if IS_IN(rtld) +# define PTR_MANGLE(dst, src, tmp) \ + ldih tmp, __pointer_chk_guard_local ($29) !gprelhigh; \ + ldl tmp, __pointer_chk_guard_local (tmp) !gprellow; \ + xor src, tmp, dst +# define PTR_MANGLE2(dst, src, tmp) xor src, tmp, dst +# elif defined SHARED +# define PTR_MANGLE(dst, src, tmp) \ + ldl tmp, __pointer_chk_guard; \ + xor src, tmp, dst +# else +# define PTR_MANGLE(dst, src, tmp) \ + ldl tmp, __pointer_chk_guard_local; \ + xor src, tmp, dst +# endif +# define PTR_MANGLE2(dst, src, tmp) xor src, tmp, dst +# define PTR_DEMANGLE(dst, tmp) PTR_MANGLE (dst, dst, tmp) +# define PTR_DEMANGLE2(dst, tmp) PTR_MANGLE2 (dst, dst, tmp) +#else +# include +# if (IS_IN(rtld) || (!defined SHARED && (IS_IN(libc) || IS_IN(libpthread)))) +extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden; +# define PTR_MANGLE(var) \ + (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard_local) +# else +extern uintptr_t __pointer_chk_guard attribute_relro; +# define PTR_MANGLE(var) \ + (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard) +# endif +# define PTR_DEMANGLE(var) PTR_MANGLE (var) +#endif /* ASSEMBLER */ + +#endif /* _LINUX_SW_64_SYSDEP_H */ diff --git a/sysdeps/unix/sysv/linux/sw_64/vfork.S b/sysdeps/unix/sysv/linux/sw_64/vfork.S new file mode 100644 index 00000000..a79eb93a --- /dev/null +++ b/sysdeps/unix/sysv/linux/sw_64/vfork.S @@ -0,0 +1,41 @@ +/* Copyright (C) 2004-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +#include +#include + +ENTRY(__libc_vfork) + PSEUDO_PROLOGUE + + /* Load the thread pointer value in A1 across the vfork. */ + sys_call 0x9e + mov v0, a1 + + ldi v0, SYS_ify(vfork) + sys_call HMC_callsys + + /* Normal error check and return. */ + bne a3, SYSCALL_ERROR_LABEL + ret + +PSEUDO_END (__libc_vfork) + +#if IS_IN (libc) +weak_alias (__libc_vfork, vfork) +strong_alias (__libc_vfork, __vfork) +libc_hidden_def (__vfork) +#endif -- 2.25.1