From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-oi1-x235.google.com (mail-oi1-x235.google.com [IPv6:2607:f8b0:4864:20::235]) by sourceware.org (Postfix) with ESMTPS id C68C438582B4 for ; Wed, 20 Jul 2022 14:35:49 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org C68C438582B4 Received: by mail-oi1-x235.google.com with SMTP id s204so11086463oif.5 for ; Wed, 20 Jul 2022 07:35:49 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:date:mime-version:user-agent:subject :content-language:to:references:from:organization:in-reply-to :content-transfer-encoding; bh=y6BQS0VRzR/hAXmvsxrhY0MH/48Sob7OZbWMESAGG4w=; b=vq/dhbwRkSm3msfCR8YkM4zBfNVWujnGlgLvCjB4PJifm/UPMWRrF+3ZIKA+DkefUB F82EMqDZRhoOTAFniwJ6EPRSlDGXjhflWkS4ln6A9rKHg2RDpk02UL5PiOmTDd3Hevli F4qaQcdYF8OzW203YQmr4gh8sGi1GJch5iNIC3Dt9z7vCD2fRW24u9//W3CuWJoI/T23 eYrD0FtUzsZIR8BmOU9aMYJUmzFlkSGzMKPqPrj5k3nmkuFzxPxOKQ9ymMPycY/cP05H fd6x99FEqaqh/fXeOWuD85qtYJmPG+itcokm5bx79b6ErpFpMj2vGJHgigu7WJhir3d2 lXKw== X-Gm-Message-State: AJIora+7M5wZQpfj22tnz43jkolB/CxKLR7B5XzGT7pIdgWV81eCSu+2 bnaVTK4qqhoFVh6jxOzvpJDeqA== X-Google-Smtp-Source: AGRyM1uSMCn2R2MlFc5EHYWqj3PkGOF2PB93Ze1Qk1ijxgTjPa1tRshGpcrwIeY/Z8MRdwBmxsmp7Q== X-Received: by 2002:a05:6808:20a0:b0:33a:8965:3a92 with SMTP id s32-20020a05680820a000b0033a89653a92mr2333100oiw.62.1658327748714; Wed, 20 Jul 2022 07:35:48 -0700 (PDT) Received: from ?IPV6:2804:431:c7cb:8ded:dd7a:8a21:1a2b:76c5? ([2804:431:c7cb:8ded:dd7a:8a21:1a2b:76c5]) by smtp.gmail.com with ESMTPSA id c6-20020a9d6846000000b0061cc1ba78e5sm274308oto.3.2022.07.20.07.35.46 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 20 Jul 2022 07:35:48 -0700 (PDT) Message-ID: Date: Wed, 20 Jul 2022 11:35:45 -0300 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:102.0) Gecko/20100101 Thunderbird/102.0.2 Subject: Re: [PATCH v7 07/13] LoongArch: Linux Syscall Interface Content-Language: en-US To: caiyinyu , libc-alpha@sourceware.org, joseph_myers@mentor.com, carlos@redhat.com, i.swmail@xen0n.name References: <20220719012056.1461897-1-caiyinyu@loongson.cn> <20220719012056.1461897-8-caiyinyu@loongson.cn> From: Adhemerval Zanella Netto Organization: Linaro In-Reply-To: <20220719012056.1461897-8-caiyinyu@loongson.cn> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-12.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, NICE_REPLY_A, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 20 Jul 2022 14:35:54 -0000 LGTM, thanks. Reviewed-by: Adhemerval Zanella On 18/07/22 22:20, caiyinyu wrote: > --- > sysdeps/loongarch/abort-instr.h | 2 + > sysdeps/loongarch/hp-timing.h | 42 +++ > .../unix/sysv/linux/loongarch/arch-syscall.h | 301 ++++++++++++++++ > sysdeps/unix/sysv/linux/loongarch/clone.S | 96 ++++++ > sysdeps/unix/sysv/linux/loongarch/clone3.S | 83 +++++ > sysdeps/unix/sysv/linux/loongarch/sysdep.S | 53 +++ > sysdeps/unix/sysv/linux/loongarch/sysdep.h | 320 ++++++++++++++++++ > sysdeps/unix/sysv/linux/loongarch/vfork.S | 50 +++ > 8 files changed, 947 insertions(+) > create mode 100644 sysdeps/loongarch/abort-instr.h > create mode 100644 sysdeps/loongarch/hp-timing.h > create mode 100644 sysdeps/unix/sysv/linux/loongarch/arch-syscall.h > create mode 100644 sysdeps/unix/sysv/linux/loongarch/clone.S > create mode 100644 sysdeps/unix/sysv/linux/loongarch/clone3.S > create mode 100644 sysdeps/unix/sysv/linux/loongarch/sysdep.S > create mode 100644 sysdeps/unix/sysv/linux/loongarch/sysdep.h > create mode 100644 sysdeps/unix/sysv/linux/loongarch/vfork.S > > diff --git a/sysdeps/loongarch/abort-instr.h b/sysdeps/loongarch/abort-instr.h > new file mode 100644 > index 0000000000..46d3ad0871 > --- /dev/null > +++ b/sysdeps/loongarch/abort-instr.h > @@ -0,0 +1,2 @@ > +/* An instruction which should crash any program is a breakpoint. */ > +#define ABORT_INSTRUCTION asm ("break 0") > diff --git a/sysdeps/loongarch/hp-timing.h b/sysdeps/loongarch/hp-timing.h > new file mode 100644 > index 0000000000..af1da81024 > --- /dev/null > +++ b/sysdeps/loongarch/hp-timing.h > @@ -0,0 +1,42 @@ > +/* High precision, low overhead timing functions. > + Copyright (C) 2022 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 > + . */ > + > +#ifndef _HP_TIMING_H > +#define _HP_TIMING_H 1 > + > +/* We always assume having the timestamp register. */ > +#define HP_TIMING_AVAIL (1) > +#define HP_SMALL_TIMING_AVAIL (1) > + > +/* We indeed have inlined functions. */ > +#define HP_TIMING_INLINE (1) > + > +/* We use 64bit values for the times. */ > +typedef unsigned long long int hp_timing_t; > + > +/* Read the stable counter. */ > +#define HP_TIMING_NOW(Var) \ > + ({ \ > + unsigned long long int _count; \ > + asm volatile ("rdtime.d\t%0,$r0" : "=r" (_count)); \ > + (Var) = _count; \ > + }) > + > +#include > + > +#endif /* hp-timing.h */ > diff --git a/sysdeps/unix/sysv/linux/loongarch/arch-syscall.h b/sysdeps/unix/sysv/linux/loongarch/arch-syscall.h > new file mode 100644 > index 0000000000..6bb3c8adbc > --- /dev/null > +++ b/sysdeps/unix/sysv/linux/loongarch/arch-syscall.h > @@ -0,0 +1,301 @@ > +/* AUTOGENERATED by update-syscall-lists.py. */ > +#define __NR_accept 202 > +#define __NR_accept4 242 > +#define __NR_acct 89 > +#define __NR_add_key 217 > +#define __NR_adjtimex 171 > +#define __NR_bind 200 > +#define __NR_bpf 280 > +#define __NR_brk 214 > +#define __NR_capget 90 > +#define __NR_capset 91 > +#define __NR_chdir 49 > +#define __NR_chroot 51 > +#define __NR_clock_adjtime 266 > +#define __NR_clock_getres 114 > +#define __NR_clock_gettime 113 > +#define __NR_clock_nanosleep 115 > +#define __NR_clock_settime 112 > +#define __NR_clone 220 > +#define __NR_clone3 435 > +#define __NR_close 57 > +#define __NR_close_range 436 > +#define __NR_connect 203 > +#define __NR_copy_file_range 285 > +#define __NR_delete_module 106 > +#define __NR_dup 23 > +#define __NR_dup3 24 > +#define __NR_epoll_create1 20 > +#define __NR_epoll_ctl 21 > +#define __NR_epoll_pwait 22 > +#define __NR_epoll_pwait2 441 > +#define __NR_eventfd2 19 > +#define __NR_execve 221 > +#define __NR_execveat 281 > +#define __NR_exit 93 > +#define __NR_exit_group 94 > +#define __NR_faccessat 48 > +#define __NR_faccessat2 439 > +#define __NR_fadvise64 223 > +#define __NR_fallocate 47 > +#define __NR_fanotify_init 262 > +#define __NR_fanotify_mark 263 > +#define __NR_fchdir 50 > +#define __NR_fchmod 52 > +#define __NR_fchmodat 53 > +#define __NR_fchown 55 > +#define __NR_fchownat 54 > +#define __NR_fcntl 25 > +#define __NR_fdatasync 83 > +#define __NR_fgetxattr 10 > +#define __NR_finit_module 273 > +#define __NR_flistxattr 13 > +#define __NR_flock 32 > +#define __NR_fremovexattr 16 > +#define __NR_fsconfig 431 > +#define __NR_fsetxattr 7 > +#define __NR_fsmount 432 > +#define __NR_fsopen 430 > +#define __NR_fspick 433 > +#define __NR_fstatfs 44 > +#define __NR_fsync 82 > +#define __NR_ftruncate 46 > +#define __NR_futex 98 > +#define __NR_futex_waitv 449 > +#define __NR_get_mempolicy 236 > +#define __NR_get_robust_list 100 > +#define __NR_getcpu 168 > +#define __NR_getcwd 17 > +#define __NR_getdents64 61 > +#define __NR_getegid 177 > +#define __NR_geteuid 175 > +#define __NR_getgid 176 > +#define __NR_getgroups 158 > +#define __NR_getitimer 102 > +#define __NR_getpeername 205 > +#define __NR_getpgid 155 > +#define __NR_getpid 172 > +#define __NR_getppid 173 > +#define __NR_getpriority 141 > +#define __NR_getrandom 278 > +#define __NR_getresgid 150 > +#define __NR_getresuid 148 > +#define __NR_getrusage 165 > +#define __NR_getsid 156 > +#define __NR_getsockname 204 > +#define __NR_getsockopt 209 > +#define __NR_gettid 178 > +#define __NR_gettimeofday 169 > +#define __NR_getuid 174 > +#define __NR_getxattr 8 > +#define __NR_init_module 105 > +#define __NR_inotify_add_watch 27 > +#define __NR_inotify_init1 26 > +#define __NR_inotify_rm_watch 28 > +#define __NR_io_cancel 3 > +#define __NR_io_destroy 1 > +#define __NR_io_getevents 4 > +#define __NR_io_pgetevents 292 > +#define __NR_io_setup 0 > +#define __NR_io_submit 2 > +#define __NR_io_uring_enter 426 > +#define __NR_io_uring_register 427 > +#define __NR_io_uring_setup 425 > +#define __NR_ioctl 29 > +#define __NR_ioprio_get 31 > +#define __NR_ioprio_set 30 > +#define __NR_kcmp 272 > +#define __NR_kexec_file_load 294 > +#define __NR_kexec_load 104 > +#define __NR_keyctl 219 > +#define __NR_kill 129 > +#define __NR_landlock_add_rule 445 > +#define __NR_landlock_create_ruleset 444 > +#define __NR_landlock_restrict_self 446 > +#define __NR_lgetxattr 9 > +#define __NR_linkat 37 > +#define __NR_listen 201 > +#define __NR_listxattr 11 > +#define __NR_llistxattr 12 > +#define __NR_lookup_dcookie 18 > +#define __NR_lremovexattr 15 > +#define __NR_lseek 62 > +#define __NR_lsetxattr 6 > +#define __NR_madvise 233 > +#define __NR_mbind 235 > +#define __NR_membarrier 283 > +#define __NR_memfd_create 279 > +#define __NR_migrate_pages 238 > +#define __NR_mincore 232 > +#define __NR_mkdirat 34 > +#define __NR_mknodat 33 > +#define __NR_mlock 228 > +#define __NR_mlock2 284 > +#define __NR_mlockall 230 > +#define __NR_mmap 222 > +#define __NR_mount 40 > +#define __NR_mount_setattr 442 > +#define __NR_move_mount 429 > +#define __NR_move_pages 239 > +#define __NR_mprotect 226 > +#define __NR_mq_getsetattr 185 > +#define __NR_mq_notify 184 > +#define __NR_mq_open 180 > +#define __NR_mq_timedreceive 183 > +#define __NR_mq_timedsend 182 > +#define __NR_mq_unlink 181 > +#define __NR_mremap 216 > +#define __NR_msgctl 187 > +#define __NR_msgget 186 > +#define __NR_msgrcv 188 > +#define __NR_msgsnd 189 > +#define __NR_msync 227 > +#define __NR_munlock 229 > +#define __NR_munlockall 231 > +#define __NR_munmap 215 > +#define __NR_name_to_handle_at 264 > +#define __NR_nanosleep 101 > +#define __NR_nfsservctl 42 > +#define __NR_open_by_handle_at 265 > +#define __NR_open_tree 428 > +#define __NR_openat 56 > +#define __NR_openat2 437 > +#define __NR_perf_event_open 241 > +#define __NR_personality 92 > +#define __NR_pidfd_getfd 438 > +#define __NR_pidfd_open 434 > +#define __NR_pidfd_send_signal 424 > +#define __NR_pipe2 59 > +#define __NR_pivot_root 41 > +#define __NR_pkey_alloc 289 > +#define __NR_pkey_free 290 > +#define __NR_pkey_mprotect 288 > +#define __NR_ppoll 73 > +#define __NR_prctl 167 > +#define __NR_pread64 67 > +#define __NR_preadv 69 > +#define __NR_preadv2 286 > +#define __NR_prlimit64 261 > +#define __NR_process_madvise 440 > +#define __NR_process_mrelease 448 > +#define __NR_process_vm_readv 270 > +#define __NR_process_vm_writev 271 > +#define __NR_pselect6 72 > +#define __NR_ptrace 117 > +#define __NR_pwrite64 68 > +#define __NR_pwritev 70 > +#define __NR_pwritev2 287 > +#define __NR_quotactl 60 > +#define __NR_quotactl_fd 443 > +#define __NR_read 63 > +#define __NR_readahead 213 > +#define __NR_readlinkat 78 > +#define __NR_readv 65 > +#define __NR_reboot 142 > +#define __NR_recvfrom 207 > +#define __NR_recvmmsg 243 > +#define __NR_recvmsg 212 > +#define __NR_remap_file_pages 234 > +#define __NR_removexattr 14 > +#define __NR_renameat2 276 > +#define __NR_request_key 218 > +#define __NR_restart_syscall 128 > +#define __NR_rseq 293 > +#define __NR_rt_sigaction 134 > +#define __NR_rt_sigpending 136 > +#define __NR_rt_sigprocmask 135 > +#define __NR_rt_sigqueueinfo 138 > +#define __NR_rt_sigreturn 139 > +#define __NR_rt_sigsuspend 133 > +#define __NR_rt_sigtimedwait 137 > +#define __NR_rt_tgsigqueueinfo 240 > +#define __NR_sched_get_priority_max 125 > +#define __NR_sched_get_priority_min 126 > +#define __NR_sched_getaffinity 123 > +#define __NR_sched_getattr 275 > +#define __NR_sched_getparam 121 > +#define __NR_sched_getscheduler 120 > +#define __NR_sched_rr_get_interval 127 > +#define __NR_sched_setaffinity 122 > +#define __NR_sched_setattr 274 > +#define __NR_sched_setparam 118 > +#define __NR_sched_setscheduler 119 > +#define __NR_sched_yield 124 > +#define __NR_seccomp 277 > +#define __NR_semctl 191 > +#define __NR_semget 190 > +#define __NR_semop 193 > +#define __NR_semtimedop 192 > +#define __NR_sendfile 71 > +#define __NR_sendmmsg 269 > +#define __NR_sendmsg 211 > +#define __NR_sendto 206 > +#define __NR_set_mempolicy 237 > +#define __NR_set_mempolicy_home_node 450 > +#define __NR_set_robust_list 99 > +#define __NR_set_tid_address 96 > +#define __NR_setdomainname 162 > +#define __NR_setfsgid 152 > +#define __NR_setfsuid 151 > +#define __NR_setgid 144 > +#define __NR_setgroups 159 > +#define __NR_sethostname 161 > +#define __NR_setitimer 103 > +#define __NR_setns 268 > +#define __NR_setpgid 154 > +#define __NR_setpriority 140 > +#define __NR_setregid 143 > +#define __NR_setresgid 149 > +#define __NR_setresuid 147 > +#define __NR_setreuid 145 > +#define __NR_setsid 157 > +#define __NR_setsockopt 208 > +#define __NR_settimeofday 170 > +#define __NR_setuid 146 > +#define __NR_setxattr 5 > +#define __NR_shmat 196 > +#define __NR_shmctl 195 > +#define __NR_shmdt 197 > +#define __NR_shmget 194 > +#define __NR_shutdown 210 > +#define __NR_sigaltstack 132 > +#define __NR_signalfd4 74 > +#define __NR_socket 198 > +#define __NR_socketpair 199 > +#define __NR_splice 76 > +#define __NR_statfs 43 > +#define __NR_statx 291 > +#define __NR_swapoff 225 > +#define __NR_swapon 224 > +#define __NR_symlinkat 36 > +#define __NR_sync 81 > +#define __NR_sync_file_range 84 > +#define __NR_syncfs 267 > +#define __NR_sysinfo 179 > +#define __NR_syslog 116 > +#define __NR_tee 77 > +#define __NR_tgkill 131 > +#define __NR_timer_create 107 > +#define __NR_timer_delete 111 > +#define __NR_timer_getoverrun 109 > +#define __NR_timer_gettime 108 > +#define __NR_timer_settime 110 > +#define __NR_timerfd_create 85 > +#define __NR_timerfd_gettime 87 > +#define __NR_timerfd_settime 86 > +#define __NR_times 153 > +#define __NR_tkill 130 > +#define __NR_truncate 45 > +#define __NR_umask 166 > +#define __NR_umount2 39 > +#define __NR_uname 160 > +#define __NR_unlinkat 35 > +#define __NR_unshare 97 > +#define __NR_userfaultfd 282 > +#define __NR_utimensat 88 > +#define __NR_vhangup 58 > +#define __NR_vmsplice 75 > +#define __NR_wait4 260 > +#define __NR_waitid 95 > +#define __NR_write 64 > +#define __NR_writev 66 > diff --git a/sysdeps/unix/sysv/linux/loongarch/clone.S b/sysdeps/unix/sysv/linux/loongarch/clone.S > new file mode 100644 > index 0000000000..c73245be82 > --- /dev/null > +++ b/sysdeps/unix/sysv/linux/loongarch/clone.S > @@ -0,0 +1,96 @@ > +/* The clone syscall wrapper. > + Copyright (C) 2022 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 > + . */ > + > +/* 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 > +#include > +#define _ERRNO_H 1 > +#include > +#include > +#include "tcb-offsets.h" > + > +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, > + void *parent_tidptr, void *tls, void *child_tidptr) */ > + > +ENTRY (__clone) > + > + /* Align stack to 16. */ > + BSTRINS a1, zero, 3, 0 > + > + /* Sanity check arguments. */ > + beqz a0, L (invalid) /* No NULL function pointers. */ > + beqz a1, L (invalid) /* No NULL stack pointers. */ > + > + ADDI a1, a1, -16 /* Reserve argument save space. */ > + REG_S a0, a1, 0 /* Save function pointer. */ > + REG_S a3, a1, SZREG /* Save argument pointer. */ > + > + /* The syscall expects the args to be in different slots. */ > + or a0, a2, zero > + or a2, a4, zero > + or a3, a6, zero > + or a4, a5, zero > + > + /* Do the system call. */ > + LI a7,__NR_clone > + syscall 0 > + > + blt a0, zero ,L (error) > + beqz a0,L (thread_start) > + > + /* Successful return from the parent. */ > + ret > + > +L (invalid): > + LI a0, -EINVAL > + > + /* Something bad happened -- no child created. */ > +L (error): > + b __syscall_error > + > +END (__clone) > + > +/* 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. */ > +ENTRY (__thread_start) > +L (thread_start): > + > +/* Terminate call stack by noting ra is undefined. Use a dummy > + .cfi_label to force starting the FDE. */ > + .cfi_label .Ldummy > + cfi_undefined (1) > + > + /* Restore the arg for user's function. */ > + REG_L a1, sp, 0 /* Function pointer. */ > + REG_L a0, sp, SZREG /* Argument pointer. */ > + > + /* Call the user's function. */ > + jirl ra, a1, 0 > + > + /* Call exit with the function's return value. */ > + LI a7, __NR_exit > + syscall 0 > + > + END (__thread_start) > + > +libc_hidden_def (__clone) > +weak_alias (__clone, clone) > diff --git a/sysdeps/unix/sysv/linux/loongarch/clone3.S b/sysdeps/unix/sysv/linux/loongarch/clone3.S > new file mode 100644 > index 0000000000..38be4c809b > --- /dev/null > +++ b/sysdeps/unix/sysv/linux/loongarch/clone3.S > @@ -0,0 +1,83 @@ > +/* The clone3 syscall wrapper. > + Copyright (C) 2022 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 > + . */ > + > +/* clone3() is even more special than fork() as it mucks with stacks > + and invokes a function in the right context after its all over. */ > + > +#include > +#include > +#define _ERRNO_H 1 > +#include > +#include > +#include "tcb-offsets.h" > + > +/* int clone3(struct clone_args *cl_args, size_t size, > + int (*func)(void *arg), void *arg); */ > + > +ENTRY (__clone3) > + > + /* Sanity check arguments. */ > + beqz a0, L (invalid) /* No NULL cl_args pointer. */ > + beqz a2, L (invalid) /* No NULL function pointer. */ > + > + /* Do the system call. */ > + LI a7, __NR_clone3 > + syscall 0 > + > + blt a0, zero ,L (error) > + beqz a0, L (thread_start3) > + > + /* Successful return from the parent. */ > + ret > + > +L (invalid): > + LI a0, -EINVAL > + > + /* Something bad happened -- no child created. */ > +L (error): > + b __syscall_error > + > +END (__clone3) > + > +/* 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. */ > +ENTRY (__thread_start3) > +L (thread_start3): > + > +/* Terminate call stack by noting ra is undefined. Use a dummy > + .cfi_label to force starting the FDE. */ > + .cfi_label .Ldummy > + cfi_undefined (1) > + > + /* Align stack to 16. */ > + BSTRINS sp, zero, 3, 0 > + > + /* Set up arguments for the function call. */ > + move a0, a3 /* Argument. */ > + jirl ra, a2, 0 /* Call function. */ > + > + /* Call exit with the function's return value. */ > + LI a7, __NR_exit > + syscall 0 > + > + END (__thread_start3) > + > +libc_hidden_def (__clone3) > +weak_alias (__clone3, clone3) > diff --git a/sysdeps/unix/sysv/linux/loongarch/sysdep.S b/sysdeps/unix/sysv/linux/loongarch/sysdep.S > new file mode 100644 > index 0000000000..a4db2a97b5 > --- /dev/null > +++ b/sysdeps/unix/sysv/linux/loongarch/sysdep.S > @@ -0,0 +1,53 @@ > +/* syscall error handlers > + Copyright (C) 2022 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 > + > +#if IS_IN (libc) > +# define errno __libc_errno > +#endif > + > +ENTRY (__syscall_error) > +/* Fall through to __syscall_set_errno */ > +END (__syscall_error) > + > +/* Non-standard calling convention: argument in a0, return address in t0, > + and clobber only t1. > + */ > +ENTRY (__syscall_set_errno) > + > +/* We got here because a0 < 0, but only codes in the range [-4095, -1] > + represent errors. Otherwise, just return the result normally. > + */ > + li.d t1, -4096 > + bgeu t1, a0, L (out) > + sub.w a0, zero, a0 > +#if RTLD_PRIVATE_ERRNO > + la t1, rtld_errno > +#elif defined(__PIC__) > + la.tls.ie t1, errno > + add.d t1, tp, t1 > +#else > + la.tls.le t1, errno > + add.d t1, tp, t1 > +#endif > + st.w a0, t1, 0 > + li.d a0, -1 > +L (out): > + ret > +END (__syscall_set_errno) > diff --git a/sysdeps/unix/sysv/linux/loongarch/sysdep.h b/sysdeps/unix/sysv/linux/loongarch/sysdep.h > new file mode 100644 > index 0000000000..c586df819c > --- /dev/null > +++ b/sysdeps/unix/sysv/linux/loongarch/sysdep.h > @@ -0,0 +1,320 @@ > +/* Assembly macros for LoongArch. > + Copyright (C) 2022 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 > + . */ > + > +#ifndef _LINUX_LOONGARCH_SYSDEP_H > +#define _LINUX_LOONGARCH_SYSDEP_H 1 > + > +#include > +#include > + > +#ifdef __ASSEMBLER__ > + > +#include > +#define ret jirl zero, ra, 0 > +#define L(label) .L##label > + > +/* Performs a system call, handling errors by setting errno. Linux indicates > + errors by setting a0 to a value between -1 and -4095. */ > +#undef PSEUDO > +#define PSEUDO(name, syscall_name, args) \ > + ENTRY (name); \ > + li.d a7, SYS_ify (syscall_name); \ > + syscall 0; \ > + li.d a7, -4096; \ > + bltu a7, a0, .Lsyscall_error##name; > + > +#undef PSEUDO_END > +#define PSEUDO_END(sym) \ > + SYSCALL_ERROR_HANDLER (sym); \ > + ret; \ > + END (sym); > + > +#if !IS_IN(libc) > +#if RTLD_PRIVATE_ERRNO > + > +#define SYSCALL_ERROR_HANDLER(name) \ > + .Lsyscall_error##name : la t0, rtld_errno; \ > + sub.w a0, zero, a0; \ > + st.w a0, t0, 0; \ > + li.d a0, -1; > + > +#else > + > +#define SYSCALL_ERROR_HANDLER(name) \ > + .Lsyscall_error##name : la.tls.ie t0, errno; \ > + add.d t0, tp, t0; \ > + sub.w a0, zero, a0; \ > + st.w a0, t0, 0; \ > + li.d a0, -1; > + > +#endif > +#else > + > +#define SYSCALL_ERROR_HANDLER(name) .Lsyscall_error##name : b __syscall_error; > + > +#endif > + > +/* Performs a system call, not setting errno. */ > +#undef PSEUDO_NEORRNO > +#define PSEUDO_NOERRNO(name, syscall_name, args) \ > + ENTRY (name); \ > + li.d a7, SYS_ify (syscall_name); \ > + syscall 0; > + > +#undef PSEUDO_END_NOERRNO > +#define PSEUDO_END_NOERRNO(name) END (name); > + > +#undef ret_NOERRNO > +#define ret_NOERRNO ret > + > +/* Perfroms a system call, returning the error code. */ > +#undef PSEUDO_ERRVAL > +#define PSEUDO_ERRVAL(name, syscall_name, args) \ > + PSEUDO_NOERRNO (name, syscall_name, args); \ > + slli.d a0, a0, 32; \ > + srai.d a0, a0, 32; /* sign_ext */ \ > + sub.d a0, zero, a0; > + > +#undef PSEUDO_END_ERRVAL > +#define PSEUDO_END_ERRVAL(name) END (name); > + > +#undef ret_ERRVAL > +#define ret_ERRVAL ret > + > +#endif /* __ASSEMBLER__ */ > + > +/* In order to get __set_errno() definition in INLINE_SYSCALL. */ > +#ifndef __ASSEMBLER__ > +#include > +#endif > + > +#include > + > +#undef SYS_ify > +#define SYS_ify(syscall_name) __NR_##syscall_name > + > +#ifndef __ASSEMBLER__ > + > +#define VDSO_NAME "LINUX_2.6" > +#define VDSO_HASH 61765110 > + > +/* List of system calls which are supported as vsyscalls. */ > +#define HAVE_CLOCK_GETRES64_VSYSCALL "__vdso_clock_getres" > +#define HAVE_CLOCK_GETTIME64_VSYSCALL "__vdso_clock_gettime" > +#define HAVE_GETCPU_VSYSCALL "__vdso_getcpu" > + > +#define HAVE_CLONE3_WRAPPER 1 > + > +#define INTERNAL_SYSCALL(name, nr, args...) \ > + internal_syscall##nr (SYS_ify (name), args) > + > +#define INTERNAL_SYSCALL_NCS(number, nr, args...) \ > + internal_syscall##nr (number, args) > + > +#define internal_syscall0(number, dummy...) \ > + ({ \ > + long int _sys_result; \ > +\ > + { \ > + register long int __a7 asm ("$a7") = number; \ > + register long int __a0 asm ("$a0"); \ > + __asm__ volatile ("syscall 0\n\t" \ > + : "=r"(__a0) \ > + : "r"(__a7) \ > + : __SYSCALL_CLOBBERS); \ > + _sys_result = __a0; \ > + } \ > + _sys_result; \ > + }) > + > +#define internal_syscall1(number, arg0) \ > + ({ \ > + long int _sys_result; \ > +\ > + { \ > + long int _arg0 = (long int) (arg0); \ > + register long int __a7 asm ("$a7") = number; \ > + register long int __a0 asm ("$a0") = _arg0; \ > + __asm__ volatile ("syscall 0\n\t" \ > + : "+r"(__a0) \ > + : "r"(__a7) \ > + : __SYSCALL_CLOBBERS); \ > + _sys_result = __a0; \ > + } \ > + _sys_result; \ > + }) > + > +#define internal_syscall2(number, arg0, arg1) \ > + ({ \ > + long int _sys_result; \ > +\ > + { \ > + long int _arg0 = (long int) (arg0); \ > + long int _arg1 = (long int) (arg1); \ > + register long int __a7 asm ("$a7") = number; \ > + register long int __a0 asm ("$a0") = _arg0; \ > + register long int __a1 asm ("$a1") = _arg1; \ > + __asm__ volatile ("syscall 0\n\t" \ > + : "+r"(__a0) \ > + : "r"(__a7), "r"(__a1) \ > + : __SYSCALL_CLOBBERS); \ > + _sys_result = __a0; \ > + } \ > + _sys_result; \ > + }) > + > +#define internal_syscall3(number, arg0, arg1, arg2) \ > + ({ \ > + long int _sys_result; \ > +\ > + { \ > + long int _arg0 = (long int) (arg0); \ > + long int _arg1 = (long int) (arg1); \ > + long int _arg2 = (long int) (arg2); \ > + register long int __a7 asm ("$a7") = number; \ > + register long int __a0 asm ("$a0") = _arg0; \ > + register long int __a1 asm ("$a1") = _arg1; \ > + register long int __a2 asm ("$a2") = _arg2; \ > + __asm__ volatile ("syscall 0\n\t" \ > + : "+r"(__a0) \ > + : "r"(__a7), "r"(__a1), "r"(__a2) \ > + : __SYSCALL_CLOBBERS); \ > + _sys_result = __a0; \ > + } \ > + _sys_result; \ > + }) > + > +#define internal_syscall4(number, arg0, arg1, arg2, arg3) \ > + ({ \ > + long int _sys_result; \ > +\ > + { \ > + long int _arg0 = (long int) (arg0); \ > + long int _arg1 = (long int) (arg1); \ > + long int _arg2 = (long int) (arg2); \ > + long int _arg3 = (long int) (arg3); \ > + register long int __a7 asm ("$a7") = number; \ > + register long int __a0 asm ("$a0") = _arg0; \ > + register long int __a1 asm ("$a1") = _arg1; \ > + register long int __a2 asm ("$a2") = _arg2; \ > + register long int __a3 asm ("$a3") = _arg3; \ > + __asm__ volatile ("syscall 0\n\t" \ > + : "+r"(__a0) \ > + : "r"(__a7), "r"(__a1), "r"(__a2), "r"(__a3) \ > + : __SYSCALL_CLOBBERS); \ > + _sys_result = __a0; \ > + } \ > + _sys_result; \ > + }) > + > +#define internal_syscall5(number, arg0, arg1, arg2, arg3, arg4) \ > + ({ \ > + long int _sys_result; \ > +\ > + { \ > + long int _arg0 = (long int) (arg0); \ > + long int _arg1 = (long int) (arg1); \ > + long int _arg2 = (long int) (arg2); \ > + long int _arg3 = (long int) (arg3); \ > + long int _arg4 = (long int) (arg4); \ > + register long int __a7 asm ("$a7") = number; \ > + register long int __a0 asm ("$a0") = _arg0; \ > + register long int __a1 asm ("$a1") = _arg1; \ > + register long int __a2 asm ("$a2") = _arg2; \ > + register long int __a3 asm ("$a3") = _arg3; \ > + register long int __a4 asm ("$a4") = _arg4; \ > + __asm__ volatile ("syscall 0\n\t" \ > + : "+r"(__a0) \ > + : "r"(__a7), "r"(__a1), "r"(__a2), \ > + "r"(__a3), "r"(__a4) \ > + : __SYSCALL_CLOBBERS); \ > + _sys_result = __a0; \ > + } \ > + _sys_result; \ > + }) > + > +#define internal_syscall6(number, arg0, arg1, arg2, arg3, arg4, arg5) \ > + ({ \ > + long int _sys_result; \ > +\ > + { \ > + long int _arg0 = (long int) (arg0); \ > + long int _arg1 = (long int) (arg1); \ > + long int _arg2 = (long int) (arg2); \ > + long int _arg3 = (long int) (arg3); \ > + long int _arg4 = (long int) (arg4); \ > + long int _arg5 = (long int) (arg5); \ > + register long int __a7 asm ("$a7") = number; \ > + register long int __a0 asm ("$a0") = _arg0; \ > + register long int __a1 asm ("$a1") = _arg1; \ > + register long int __a2 asm ("$a2") = _arg2; \ > + register long int __a3 asm ("$a3") = _arg3; \ > + register long int __a4 asm ("$a4") = _arg4; \ > + register long int __a5 asm ("$a5") = _arg5; \ > + __asm__ volatile ("syscall 0\n\t" \ > + : "+r"(__a0) \ > + : "r"(__a7), "r"(__a1), "r"(__a2), "r"(__a3), \ > + "r"(__a4), "r"(__a5) \ > + : __SYSCALL_CLOBBERS); \ > + _sys_result = __a0; \ > + } \ > + _sys_result; \ > + }) > + > +#define internal_syscall7(number, arg0, arg1, arg2, arg3, arg4, arg5, arg6) \ > + ({ \ > + long int _sys_result; \ > +\ > + { \ > + long int _arg0 = (long int) (arg0); \ > + long int _arg1 = (long int) (arg1); \ > + long int _arg2 = (long int) (arg2); \ > + long int _arg3 = (long int) (arg3); \ > + long int _arg4 = (long int) (arg4); \ > + long int _arg5 = (long int) (arg5); \ > + long int _arg6 = (long int) (arg6); \ > + register long int __a7 asm ("$a7") = number; \ > + register long int __a0 asm ("$a0") = _arg0; \ > + register long int __a1 asm ("$a1") = _arg1; \ > + register long int __a2 asm ("$a2") = _arg2; \ > + register long int __a3 asm ("$a3") = _arg3; \ > + register long int __a4 asm ("$a4") = _arg4; \ > + register long int __a5 asm ("$a5") = _arg5; \ > + register long int __a6 asm ("$a6") = _arg6; \ > + __asm__ volatile ("syscall 0\n\t" \ > + : "+r"(__a0) \ > + : "r"(__a7), "r"(__a1), "r"(__a2), "r"(__a3), \ > + "r"(__a4), "r"(__a5), "r"(__a6) \ > + : __SYSCALL_CLOBBERS); \ > + _sys_result = __a0; \ > + } \ > + _sys_result; \ > + }) > + > +#define __SYSCALL_CLOBBERS \ > + "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", "memory" > + > +extern long int __syscall_error (long int neg_errno); > + > +#endif /* ! __ASSEMBLER__ */ > + > +/* Pointer mangling is not supported. */ > +#define PTR_MANGLE(var) (void) (var) > +#define PTR_DEMANGLE(var) (void) (var) > + > +#endif /* linux/loongarch/sysdep.h */ > diff --git a/sysdeps/unix/sysv/linux/loongarch/vfork.S b/sysdeps/unix/sysv/linux/loongarch/vfork.S > new file mode 100644 > index 0000000000..fcc84e3549 > --- /dev/null > +++ b/sysdeps/unix/sysv/linux/loongarch/vfork.S > @@ -0,0 +1,50 @@ > +/* vfork for Linux. > + Copyright (C) 2022 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 > +#define _ERRNO_H 1 > +#include > + > +/* Clone the calling process, but without copying the whole address space. > + The calling process is suspended until the new process exits or is > + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, > + and the process ID of the new process to the old process. */ > + > +ENTRY (__vfork) > + > + li.d a0, 0x4111 /* CLONE_VM | CLONE_VFORK | SIGCHLD */ > + add.d a1, zero, sp > + > + /* Do the system call. */ > + li.d a7, __NR_clone > + syscall 0 > + > + blt a0, zero ,L (error) > + > + ret > + > +L (error): > + b __syscall_error > + > +END (__vfork) > + > +libc_hidden_def (__vfork) > + > +weak_alias (__vfork, vfork) > +strong_alias (__vfork, __libc_vfork)