diff options
author | Waldemar Brodkorb <wbx@uclibc-ng.org> | 2016-10-04 06:51:35 +0200 |
---|---|---|
committer | Waldemar Brodkorb <wbx@openadk.org> | 2017-02-01 17:48:38 +0100 |
commit | dba942c80dc2cfa5768a856fff98e22a755fdd27 (patch) | |
tree | 371e775cb6dfec085945f6834aeb9d3b6de36fbe /libc | |
parent | 9b457baf8d46329f7d7ee2aa084022bb0df88551 (diff) |
add experimental aarch64 support
Ported over from GNU C Library and runtime tested in Qemu.
Diffstat (limited to 'libc')
38 files changed, 2312 insertions, 75 deletions
diff --git a/libc/string/aarch64/Makefile b/libc/string/aarch64/Makefile new file mode 100644 index 000000000..0a95346fd --- /dev/null +++ b/libc/string/aarch64/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir:=../../../ +top_builddir:=../../../ +all: objs +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/string/aarch64/memcpy.S b/libc/string/aarch64/memcpy.S new file mode 100644 index 000000000..87b2552a2 --- /dev/null +++ b/libc/string/aarch64/memcpy.S @@ -0,0 +1,230 @@ +/* Copyright (C) 2012-2017 Free Software Foundation, Inc. + + 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 + <http://www.gnu.org/licenses/>. */ + +#include <sysdep.h> + +/* Assumptions: + * + * ARMv8-a, AArch64, unaligned accesses. + * + */ + +#define dstin x0 +#define src x1 +#define count x2 +#define dst x3 +#define srcend x4 +#define dstend x5 +#define A_l x6 +#define A_lw w6 +#define A_h x7 +#define A_hw w7 +#define B_l x8 +#define B_lw w8 +#define B_h x9 +#define C_l x10 +#define C_h x11 +#define D_l x12 +#define D_h x13 +#define E_l src +#define E_h count +#define F_l srcend +#define F_h dst +#define G_l count +#define G_h dst +#define tmp1 x14 + +ENTRY (memcpy) + + prfm PLDL1KEEP, [src] + add srcend, src, count + add dstend, dstin, count + cmp count, 16 + b.ls L(copy16) + cmp count, 96 + b.hi L(copy_long) + + /* Medium copies: 17..96 bytes. */ + sub tmp1, count, 1 + ldp A_l, A_h, [src] + tbnz tmp1, 6, L(copy96) + ldp D_l, D_h, [srcend, -16] + tbz tmp1, 5, 1f + ldp B_l, B_h, [src, 16] + ldp C_l, C_h, [srcend, -32] + stp B_l, B_h, [dstin, 16] + stp C_l, C_h, [dstend, -32] +1: + stp A_l, A_h, [dstin] + stp D_l, D_h, [dstend, -16] + ret + + .p2align 4 + /* Small copies: 0..16 bytes. */ +L(copy16): + cmp count, 8 + b.lo 1f + ldr A_l, [src] + ldr A_h, [srcend, -8] + str A_l, [dstin] + str A_h, [dstend, -8] + ret + .p2align 4 +1: + tbz count, 2, 1f + ldr A_lw, [src] + ldr A_hw, [srcend, -4] + str A_lw, [dstin] + str A_hw, [dstend, -4] + ret + + /* Copy 0..3 bytes. Use a branchless sequence that copies the same + byte 3 times if count==1, or the 2nd byte twice if count==2. */ +1: + cbz count, 2f + lsr tmp1, count, 1 + ldrb A_lw, [src] + ldrb A_hw, [srcend, -1] + ldrb B_lw, [src, tmp1] + strb A_lw, [dstin] + strb B_lw, [dstin, tmp1] + strb A_hw, [dstend, -1] +2: ret + + .p2align 4 + /* Copy 64..96 bytes. Copy 64 bytes from the start and + 32 bytes from the end. */ +L(copy96): + ldp B_l, B_h, [src, 16] + ldp C_l, C_h, [src, 32] + ldp D_l, D_h, [src, 48] + ldp E_l, E_h, [srcend, -32] + ldp F_l, F_h, [srcend, -16] + stp A_l, A_h, [dstin] + stp B_l, B_h, [dstin, 16] + stp C_l, C_h, [dstin, 32] + stp D_l, D_h, [dstin, 48] + stp E_l, E_h, [dstend, -32] + stp F_l, F_h, [dstend, -16] + ret + + /* Align DST to 16 byte alignment so that we don't cross cache line + boundaries on both loads and stores. There are at least 96 bytes + to copy, so copy 16 bytes unaligned and then align. The loop + copies 64 bytes per iteration and prefetches one iteration ahead. */ + + .p2align 4 +L(copy_long): + and tmp1, dstin, 15 + bic dst, dstin, 15 + ldp D_l, D_h, [src] + sub src, src, tmp1 + add count, count, tmp1 /* Count is now 16 too large. */ + ldp A_l, A_h, [src, 16] + stp D_l, D_h, [dstin] + ldp B_l, B_h, [src, 32] + ldp C_l, C_h, [src, 48] + ldp D_l, D_h, [src, 64]! + subs count, count, 128 + 16 /* Test and readjust count. */ + b.ls 2f +1: + stp A_l, A_h, [dst, 16] + ldp A_l, A_h, [src, 16] + stp B_l, B_h, [dst, 32] + ldp B_l, B_h, [src, 32] + stp C_l, C_h, [dst, 48] + ldp C_l, C_h, [src, 48] + stp D_l, D_h, [dst, 64]! + ldp D_l, D_h, [src, 64]! + subs count, count, 64 + b.hi 1b + + /* Write the last full set of 64 bytes. The remainder is at most 64 + bytes, so it is safe to always copy 64 bytes from the end even if + there is just 1 byte left. */ +2: + ldp E_l, E_h, [srcend, -64] + stp A_l, A_h, [dst, 16] + ldp A_l, A_h, [srcend, -48] + stp B_l, B_h, [dst, 32] + ldp B_l, B_h, [srcend, -32] + stp C_l, C_h, [dst, 48] + ldp C_l, C_h, [srcend, -16] + stp D_l, D_h, [dst, 64] + stp E_l, E_h, [dstend, -64] + stp A_l, A_h, [dstend, -48] + stp B_l, B_h, [dstend, -32] + stp C_l, C_h, [dstend, -16] + ret + + .p2align 4 +L(move_long): + cbz tmp1, 3f + + add srcend, src, count + add dstend, dstin, count + + /* Align dstend to 16 byte alignment so that we don't cross cache line + boundaries on both loads and stores. There are at least 96 bytes + to copy, so copy 16 bytes unaligned and then align. The loop + copies 64 bytes per iteration and prefetches one iteration ahead. */ + + and tmp1, dstend, 15 + ldp D_l, D_h, [srcend, -16] + sub srcend, srcend, tmp1 + sub count, count, tmp1 + ldp A_l, A_h, [srcend, -16] + stp D_l, D_h, [dstend, -16] + ldp B_l, B_h, [srcend, -32] + ldp C_l, C_h, [srcend, -48] + ldp D_l, D_h, [srcend, -64]! + sub dstend, dstend, tmp1 + subs count, count, 128 + b.ls 2f + + nop +1: + stp A_l, A_h, [dstend, -16] + ldp A_l, A_h, [srcend, -16] + stp B_l, B_h, [dstend, -32] + ldp B_l, B_h, [srcend, -32] + stp C_l, C_h, [dstend, -48] + ldp C_l, C_h, [srcend, -48] + stp D_l, D_h, [dstend, -64]! + ldp D_l, D_h, [srcend, -64]! + subs count, count, 64 + b.hi 1b + + /* Write the last full set of 64 bytes. The remainder is at most 64 + bytes, so it is safe to always copy 64 bytes from the start even if + there is just 1 byte left. */ +2: + ldp G_l, G_h, [src, 48] + stp A_l, A_h, [dstend, -16] + ldp A_l, A_h, [src, 32] + stp B_l, B_h, [dstend, -32] + ldp B_l, B_h, [src, 16] + stp C_l, C_h, [dstend, -48] + ldp C_l, C_h, [src] + stp D_l, D_h, [dstend, -64] + stp G_l, G_h, [dstin, 48] + stp A_l, A_h, [dstin, 32] + stp B_l, B_h, [dstin, 16] + stp C_l, C_h, [dstin] +3: ret + +END (memcpy) +libc_hidden_def (memcpy) diff --git a/libc/string/aarch64/memset.S b/libc/string/aarch64/memset.S new file mode 100644 index 000000000..d6686bedc --- /dev/null +++ b/libc/string/aarch64/memset.S @@ -0,0 +1,189 @@ +/* Copyright (C) 2012-2017 Free Software Foundation, Inc. + + 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 + <http://www.gnu.org/licenses/>. */ + +#include <sysdep.h> + +/* Assumptions: + * + * ARMv8-a, AArch64, unaligned accesses + * + */ + +#define dstin x0 +#define val x1 +#define valw w1 +#define count x2 +#define dst x3 +#define dstend x4 +#define tmp1 x5 +#define tmp1w w5 +#define tmp2 x6 +#define tmp2w w6 +#define zva_len x7 +#define zva_lenw w7 + +ENTRY_ALIGN (memset, 6) + + dup v0.16B, valw + add dstend, dstin, count + + cmp count, 96 + b.hi L(set_long) + cmp count, 16 + b.hs L(set_medium) + mov val, v0.D[0] + + /* Set 0..15 bytes. */ + tbz count, 3, 1f + str val, [dstin] + str val, [dstend, -8] + ret + nop +1: tbz count, 2, 2f + str valw, [dstin] + str valw, [dstend, -4] + ret +2: cbz count, 3f + strb valw, [dstin] + tbz count, 1, 3f + strh valw, [dstend, -2] +3: ret + + /* Set 17..96 bytes. */ +L(set_medium): + str q0, [dstin] + tbnz count, 6, L(set96) + str q0, [dstend, -16] + tbz count, 5, 1f + str q0, [dstin, 16] + str q0, [dstend, -32] +1: ret + + .p2align 4 + /* Set 64..96 bytes. Write 64 bytes from the start and + 32 bytes from the end. */ +L(set96): + str q0, [dstin, 16] + stp q0, q0, [dstin, 32] + stp q0, q0, [dstend, -32] + ret + + .p2align 3 + nop +L(set_long): + and valw, valw, 255 + bic dst, dstin, 15 + str q0, [dstin] + cmp count, 256 + ccmp valw, 0, 0, cs + b.eq L(try_zva) +L(no_zva): + sub count, dstend, dst /* Count is 16 too large. */ + add dst, dst, 16 + sub count, count, 64 + 16 /* Adjust count and bias for loop. */ +1: stp q0, q0, [dst], 64 + stp q0, q0, [dst, -32] +L(tail64): + subs count, count, 64 + b.hi 1b +2: stp q0, q0, [dstend, -64] + stp q0, q0, [dstend, -32] + ret + + .p2align 3 +L(try_zva): + mrs tmp1, dczid_el0 + tbnz tmp1w, 4, L(no_zva) + and tmp1w, tmp1w, 15 + cmp tmp1w, 4 /* ZVA size is 64 bytes. */ + b.ne L(zva_128) + + /* Write the first and last 64 byte aligned block using stp rather + than using DC ZVA. This is faster on some cores. + */ +L(zva_64): + str q0, [dst, 16] + stp q0, q0, [dst, 32] + bic dst, dst, 63 + stp q0, q0, [dst, 64] + stp q0, q0, [dst, 96] + sub count, dstend, dst /* Count is now 128 too large. */ + sub count, count, 128+64+64 /* Adjust count and bias for loop. */ + add dst, dst, 128 + nop +1: dc zva, dst + add dst, dst, 64 + subs count, count, 64 + b.hi 1b + stp q0, q0, [dst, 0] + stp q0, q0, [dst, 32] + stp q0, q0, [dstend, -64] + stp q0, q0, [dstend, -32] + ret + + .p2align 3 +L(zva_128): + cmp tmp1w, 5 /* ZVA size is 128 bytes. */ + b.ne L(zva_other) + + str q0, [dst, 16] + stp q0, q0, [dst, 32] + stp q0, q0, [dst, 64] + stp q0, q0, [dst, 96] + bic dst, dst, 127 + sub count, dstend, dst /* Count is now 128 too large. */ + sub count, count, 128+128 /* Adjust count and bias for loop. */ + add dst, dst, 128 +1: dc zva, dst + add dst, dst, 128 + subs count, count, 128 + b.hi 1b + stp q0, q0, [dstend, -128] + stp q0, q0, [dstend, -96] + stp q0, q0, [dstend, -64] + stp q0, q0, [dstend, -32] + ret + +L(zva_other): + mov tmp2w, 4 + lsl zva_lenw, tmp2w, tmp1w + add tmp1, zva_len, 64 /* Max alignment bytes written. */ + cmp count, tmp1 + blo L(no_zva) + + sub tmp2, zva_len, 1 + add tmp1, dst, zva_len + add dst, dst, 16 + subs count, tmp1, dst /* Actual alignment bytes to write. */ + bic tmp1, tmp1, tmp2 /* Aligned dc zva start address. */ + beq 2f +1: stp q0, q0, [dst], 64 + stp q0, q0, [dst, -32] + subs count, count, 64 + b.hi 1b +2: mov dst, tmp1 + sub count, dstend, tmp1 /* Remaining bytes to write. */ + subs count, count, zva_len + b.lo 4f +3: dc zva, dst + add dst, dst, zva_len + subs count, count, zva_len + b.hs 3b +4: add count, count, zva_len + b L(tail64) + +END (memset) +libc_hidden_def (memset) diff --git a/libc/sysdeps/linux/aarch64/Makefile b/libc/sysdeps/linux/aarch64/Makefile new file mode 100644 index 000000000..86a32a613 --- /dev/null +++ b/libc/sysdeps/linux/aarch64/Makefile @@ -0,0 +1,9 @@ +# Makefile for uClibc-ng +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libc/sysdeps/linux/aarch64/Makefile.arch b/libc/sysdeps/linux/aarch64/Makefile.arch new file mode 100644 index 000000000..b38f760a8 --- /dev/null +++ b/libc/sysdeps/linux/aarch64/Makefile.arch @@ -0,0 +1,5 @@ +# Makefile for uClibc-ng +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +CSRC-y := __syscall_error.c +SSRC-y := clone.S setjmp.S syscall.S __longjmp.S bsd-setjmp.S bsd-_setjmp.S vfork.S diff --git a/libc/sysdeps/linux/aarch64/__longjmp.S b/libc/sysdeps/linux/aarch64/__longjmp.S new file mode 100644 index 000000000..e4d11b165 --- /dev/null +++ b/libc/sysdeps/linux/aarch64/__longjmp.S @@ -0,0 +1,107 @@ +/* Copyright (C) 1997-2016 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 + <http://www.gnu.org/licenses/>. */ + +#include <sysdep.h> +#include <jmpbuf-offsets.h> + +/* __longjmp(jmpbuf, val) */ + +ENTRY (__longjmp) + cfi_def_cfa(x0, 0) + cfi_offset(x19, JB_X19<<3) + cfi_offset(x20, JB_X20<<3) + cfi_offset(x21, JB_X21<<3) + cfi_offset(x22, JB_X22<<3) + cfi_offset(x23, JB_X23<<3) + cfi_offset(x24, JB_X24<<3) + cfi_offset(x25, JB_X25<<3) + cfi_offset(x26, JB_X26<<3) + cfi_offset(x27, JB_X27<<3) + cfi_offset(x28, JB_X28<<3) + cfi_offset(x29, JB_X29<<3) + cfi_offset(x30, JB_LR<<3) + + cfi_offset( d8, JB_D8<<3) + cfi_offset( d9, JB_D9<<3) + cfi_offset(d10, JB_D10<<3) + cfi_offset(d11, JB_D11<<3) + cfi_offset(d12, JB_D12<<3) + cfi_offset(d13, JB_D13<<3) + cfi_offset(d14, JB_D14<<3) + cfi_offset(d15, JB_D15<<3) + + ldp x19, x20, [x0, #JB_X19<<3] + ldp x21, x22, [x0, #JB_X21<<3] + ldp x23, x24, [x0, #JB_X23<<3] + ldp x25, x26, [x0, #JB_X25<<3] + ldp x27, x28, [x0, #JB_X27<<3] + ldp x29, x30, [x0, #JB_X29<<3] + + /* longjmp probe takes 3 arguments, address of jump buffer as + first argument (8@x0), return value as second argument (-4@x1), + and target address (8@x30), respectively. */ + //LIBC_PROBE (longjmp, 3, 8@x0, -4@x1, 8@x30) + ldp d8, d9, [x0, #JB_D8<<3] + ldp d10, d11, [x0, #JB_D10<<3] + ldp d12, d13, [x0, #JB_D12<<3] + ldp d14, d15, [x0, #JB_D14<<3] + + /* Originally this was implemented with a series of + .cfi_restore() directives. + + The theory was that cfi_restore should revert to previous + frame value is the same as the current value. In practice + this doesn't work, even after cfi_restore() gdb continues + to try to recover a previous frame value offset from x0, + which gets stuffed after a few more instructions. The + cfi_same_value() mechanism appears to work fine. */ + + cfi_same_value(x19) + cfi_same_value(x20) + cfi_same_value(x21) + cfi_same_value(x22) + cfi_same_value(x23) + cfi_same_value(x24) + cfi_same_value(x25) + cfi_same_value(x26) + cfi_same_value(x27) + cfi_same_value(x28) + cfi_same_value(x29) + cfi_same_value(x30) + cfi_same_value(d8) + cfi_same_value(d9) + cfi_same_value(d10) + cfi_same_value(d11) + cfi_same_value(d12) + cfi_same_value(d13) + cfi_same_value(d14) + cfi_same_value(d15) + ldr x5, [x0, #JB_SP<<3] + mov sp, x5 + + /* longjmp_target probe takes 3 arguments, address of jump buffer + as first argument (8@x0), return value as second argument (-4@x1), + and target address (8@x30), respectively. */ + //LIBC_PROBE (longjmp_target, 3, 8@x0, -4@x1, 8@x30) + cmp x1, #0 + mov x0, #1 + csel x0, x1, x0, ne + /* Use br instead of ret because ret is guaranteed to mispredict */ + br x30 +END (__longjmp) +libc_hidden_def(__longjmp) diff --git a/libc/sysdeps/linux/aarch64/__syscall_error.c b/libc/sysdeps/linux/aarch64/__syscall_error.c new file mode 100644 index 000000000..2b642e816 --- /dev/null +++ b/libc/sysdeps/linux/aarch64/__syscall_error.c @@ -0,0 +1,18 @@ +/* Wrapper for setting errno. + * + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <errno.h> +#include <features.h> + +/* This routine is jumped to by all the syscall handlers, to stash + * an error number into errno. */ +int __syscall_error(int err_no) attribute_hidden; +int __syscall_error(int err_no) +{ + __set_errno(-err_no); + return -1; +} diff --git a/libc/sysdeps/linux/aarch64/bits/atomic.h b/libc/sysdeps/linux/aarch64/bits/atomic.h new file mode 100644 index 000000000..66e2f57d6 --- /dev/null +++ b/libc/sysdeps/linux/aarch64/bits/atomic.h @@ -0,0 +1,172 @@ +/* Copyright (C) 2003-2017 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 + <http://www.gnu.org/licenses/>. */ + +#ifndef _AARCH64_ATOMIC_MACHINE_H +#define _AARCH64_ATOMIC_MACHINE_H 1 + +#define typeof __typeof__ + +#include <stdint.h> +#include <sysdep.h> + +typedef int8_t atomic8_t; +typedef int16_t atomic16_t; +typedef int32_t atomic32_t; +typedef int64_t atomic64_t; + +typedef uint8_t uatomic8_t; +typedef uint16_t uatomic16_t; +typedef uint32_t uatomic32_t; +typedef uint64_t uatomic64_t; + +typedef intptr_t atomicptr_t; +typedef uintptr_t uatomicptr_t; +typedef intmax_t atomic_max_t; +typedef uintmax_t uatomic_max_t; + +#define __HAVE_64B_ATOMICS 1 +#define USE_ATOMIC_COMPILER_BUILTINS 1 + +/* Compare and exchange. + For all "bool" routines, we return FALSE if exchange succesful. */ + +# define __arch_compare_and_exchange_bool_8_int(mem, newval, oldval, model) \ + ({ \ + typeof (*mem) __oldval = (oldval); \ + !__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \ + model, __ATOMIC_RELAXED); \ + }) + +# define __arch_compare_and_exchange_bool_16_int(mem, newval, oldval, model) \ + ({ \ + typeof (*mem) __oldval = (oldval); \ + !__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \ + model, __ATOMIC_RELAXED); \ + }) + +# define __arch_compare_and_exchange_bool_32_int(mem, newval, oldval, model) \ + ({ \ + typeof (*mem) __oldval = (oldval); \ + !__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \ + model, __ATOMIC_RELAXED); \ + }) + +# define __arch_compare_and_exchange_bool_64_int(mem, newval, oldval, model) \ + ({ \ + typeof (*mem) __oldval = (oldval); \ + !__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \ + model, __ATOMIC_RELAXED); \ + }) + +# define __arch_compare_and_exchange_val_8_int(mem, newval, oldval, model) \ + ({ \ + typeof (*mem) __oldval = (oldval); \ + __atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \ + model, __ATOMIC_RELAXED); \ + __oldval; \ + }) + +# define __arch_compare_and_exchange_val_16_int(mem, newval, oldval, model) \ + ({ \ + typeof (*mem) __oldval = (oldval); \ + __atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \ + model, __ATOMIC_RELAXED); \ + __oldval; \ + }) + +# define __arch_compare_and_exchange_val_32_int(mem, newval, oldval, model) \ + ({ \ + typeof (*mem) __oldval = (oldval); \ + __atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \ + model, __ATOMIC_RELAXED); \ + __oldval; \ + }) + +# define __arch_compare_and_exchange_val_64_int(mem, newval, oldval, model) \ + ({ \ + typeof (*mem) __oldval = (oldval); \ + __atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \ + model, __ATOMIC_RELAXED); \ + __oldval; \ + }) + + +/* Compare and exchange with "acquire" semantics, ie barrier after. */ + +# define atomic_compare_and_exchange_bool_acq(mem, new, old) \ + __atomic_bool_bysize (__arch_compare_and_exchange_bool, int, \ + mem, new, old, __ATOMIC_ACQUIRE) + +# define atomic_compare_and_exchange_val_acq(mem, new, old) \ + __atomic_val_bysize (__arch_compare_and_exchange_val, int, \ + mem, new, old, __ATOMIC_ACQUIRE) + +/* Compare and exchange with "release" semantics, ie barrier before. */ + +# define atomic_compare_and_exchange_val_rel(mem, new, old) \ + __atomic_val_bysize (__arch_compare_and_exchange_val, int, \ + mem, new, old, __ATOMIC_RELEASE) + + +/* Atomic exchange (without compare). */ + +# define __arch_exchange_8_int(mem, newval, model) \ + __atomic_exchange_n (mem, newval, model) + +# define __arch_exchange_16_int(mem, newval, model) \ + __atomic_exchange_n (mem, newval, model) + +# define __arch_exchange_32_int(mem, newval, model) \ + __atomic_exchange_n (mem, newval, model) + +# define __arch_exchange_64_int(mem, newval, model) \ + __atomic_exchange_n (mem, newval, model) + +# define atomic_exchange_acq(mem, value) \ + __atomic_val_bysize (__arch_exchange, int, mem, value, __ATOMIC_ACQUIRE) + +# define atomic_exchange_rel(mem, value) \ + __atomic_val_bysize (__arch_exchange, int, mem, value, __ATOMIC_RELEASE) + + +/* Atomically add value and return the previous (unincremented) value. */ + +# define __arch_exchange_and_add_8_int(mem, value, model) \ + __atomic_fetch_add (mem, value, model) + +# define __arch_exchange_and_add_16_int(mem, value, model) \ + __atomic_fetch_add (mem, value, model) + +# define __arch_exchange_and_add_32_int(mem, value, model) \ + __atomic_fetch_add (mem, value, model) + +# define __arch_exchange_and_add_64_int(mem, value, model) \ + __atomic_fetch_add (mem, value, model) + +# define atomic_exchange_and_add_acq(mem, value) \ + __atomic_val_bysize (__arch_exchange_and_add, int, mem, value, \ + __ATOMIC_ACQUIRE) + +# define atomic_exchange_and_add_rel(mem, value) \ + __atomic_val_bysize (__arch_exchange_and_add, int, mem, value, \ + __ATOMIC_RELEASE) + +/* Barrier macro. */ +#define atomic_full_barrier() __sync_synchronize() + +#endif diff --git a/libc/sysdeps/linux/aarch64/bits/endian.h b/libc/sysdeps/linux/aarch64/bits/endian.h new file mode 100644 index 000000000..a32ebc0d8 --- /dev/null +++ b/libc/sysdeps/linux/aarch64/bits/endian.h @@ -0,0 +1,30 @@ +/* Copyright (C) 1997-2016 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 + <http://www.gnu.org/licenses/>. */ + +#ifndef _ENDIAN_H +# error "Never use <bits/endian.h> directly; include <endian.h> instead." +#endif + +/* AArch64 can be either big or little endian. */ +#ifdef __AARCH64EB__ +# define __BYTE_ORDER __BIG_ENDIAN +#else +# define __BYTE_ORDER __LITTLE_ENDIAN +#endif + +#define __FLOAT_WORD_ORDER __BYTE_ORDER diff --git a/libc/sysdeps/linux/aarch64/bits/fcntl.h b/libc/sysdeps/linux/aarch64/bits/fcntl.h new file mode 100644 index 000000000..d05798f31 --- /dev/null +++ b/libc/sysdeps/linux/aarch64/bits/fcntl.h @@ -0,0 +1,329 @@ +/* O_*, F_*, FD_* bit values for the AArch64 Linux ABI. + Copyright (C) 2011-2016 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 + <http://www.gnu.org/licenses/>. */ + +#ifndef _FCNTL_H +# error "Never use <bits/fcntl.h> directly; include <fcntl.h> instead." +#endif + +#include <sys/types.h> +#ifdef __USE_GNU +# include <bits/uio.h> +#endif + +/* open/fcntl. */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* Not fcntl. */ +#define O_EXCL 0200 /* Not fcntl. */ +#define O_NOCTTY 0400 /* Not fcntl. */ +#define O_TRUNC 01000 /* Not fcntl. */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 04010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECTORY 040000 +# define O_NOFOLLOW 0100000 +# define O_DIRECT 0200000 +# define O_NOATIME 01000000 +# define O_CLOEXEC 02000000 +# define O_PATH 010000000 +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 5 /* Get record locking info. */ +#define F_SETLK64 6 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 7 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +# define F_SETOWN_EX 15 /* Get owner (thread receiving SIGIO). */ +# define F_GETOWN_EX 16 /* Set owner (thread receiving SIGIO). */ +#endif + + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notifications on a directory. */ +# define F_SETPIPE_SZ 1031 /* Set pipe page size array. */ +# define F_GETPIPE_SZ 1032 /* Set pipe page size array. */ +#endif +#ifdef __USE_XOPEN2K8 +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set. */ +#endif + +/* For F_[GET|SET]FD. */ +#define FD_CLOEXEC 1 /* Actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +# define F_RDLCK 0 /* Read lock. */ +# define F_WRLCK 1 /* Write lock. */ +# define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of BSD flock. */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for BSD flock, also used by the kernel implementation. */ +# define LOCK_SH 1 /* Shared lock. */ +# define LOCK_EX 2 /* Exclusive lock. */ +# define LOCK_NB 4 /* Or'd with one of the above to prevent + blocking. */ +# define LOCK_UN 8 /* Remove lock. */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attributes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + + +#ifdef __USE_GNU +/* Owner types. */ +enum __pid_type + { + F_OWNER_TID = 0, /* Kernel thread. */ + F_OWNER_PID, /* Process. */ + F_OWNER_PGRP, /* Process group. */ + F_OWNER_GID = F_OWNER_PGRP /* Alternative, obsolete name. */ + }; + +/* Structure to use with F_GETOWN_EX and F_SETOWN_EX. */ +struct f_owner_ex + { + enum __pid_type type; /* Owner type of ID. */ + __pid_t pid; /* ID of owner. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ + + +/* Flags for fallocate. */ +# define FALLOC_FL_KEEP_SIZE 1 /* Don't extend size of file + even if offset + len is + greater than file size. */ +# define FALLOC_FL_PUNCH_HOLE 2 /* Create a hole in the file. */ +# define FALLOC_FL_COLLAPSE_RANGE 8 /* Remove a range of a file + without leaving a + hole. */ +# define FALLOC_FL_ZERO_RANGE 16 /* Convert a range of a + file to zeros. */ + + +/* File handle structure. */ +struct file_handle +{ + unsigned int handle_bytes; + int handle_type; + /* File identifier. */ + unsigned char f_handle[0]; +}; + +/* Maximum handle size (for now). */ +# define MAX_HANDLE_SZ 128 +#endif + +__BEGIN_DECLS + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int sync_file_range (int __fd, __off64_t __offset, __off64_t __count, + unsigned int __flags); + + +/* Splice address range into a pipe. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +/* Reserve storage for the data of the file associated with FD. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +# ifndef __USE_FILE_OFFSET64 +extern int fallocate (int __fd, int __mode, __off_t __offset, __off_t __len); +# else +# ifdef __REDIRECT +extern int __REDIRECT (fallocate, (int __fd, int __mode, __off64_t __offset, + __off64_t __len), + fallocate64); +# else +# define fallocate fallocate64 +# endif +# endif +# ifdef __USE_LARGEFILE64 +extern int fallocate64 (int __fd, int __mode, __off64_t __offset, + __off64_t __len); +# endif + + +/* Map file name to file handle. */ +extern int name_to_handle_at (int __dfd, const char *__name, + struct file_handle *__handle, int *__mnt_id, + int __flags) __THROW; + +/* Open file using the file handle. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int open_by_handle_at (int __mountdirfd, struct file_handle *__handle, + int __flags); + +#endif /* use GNU */ + +__END_DECLS diff --git a/libc/sysdeps/linux/aarch64/bits/kernel_types.h b/libc/sysdeps/linux/aarch64/bits/kernel_types.h new file mode 100644 index 000000000..832b17674 --- /dev/null +++ b/libc/sysdeps/linux/aarch64/bits/kernel_types.h @@ -0,0 +1,42 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef __ASM_GENERIC_POSIX_TYPES_H +#define __ASM_GENERIC_POSIX_TYPES_H + +typedef unsigned long __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned int __kernel_mode_t; +typedef unsigned int __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef int __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef long __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef long long __kernel_loff_t; +typedef unsigned int __kernel_old_dev_t; +typedef long __kernel_long_t; +typedef unsigned long __kernel_ulong_t; + +typedef struct { + int val[2]; +} __kernel_fsid_t; + +#endif /* __ASM_GENERIC_POSIX_TYPES_H */ diff --git a/libc/sysdeps/linux/aarch64/bits/setjmp.h b/libc/sysdeps/linux/aarch64/bits/setjmp.h new file mode 100644 index 000000000..fff8616c6 --- /dev/null +++ b/libc/sysdeps/linux/aarch64/bits/setjmp.h @@ -0,0 +1,33 @@ +/* Copyright (C) 1997-2016 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 + <http://www.gnu.org/licenses/>. */ + +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead." +#endif + +#ifndef _ASM +/* Jump buffer contains: + x19-x28, x29(fp), x30(lr), (x31)sp, d8-d15. Other registers are not + saved. */ +__extension__ typedef unsigned long long __jmp_buf [22]; + +#endif +#endif diff --git a/libc/sysdeps/linux/aarch64/bits/stackinfo.h b/libc/sysdeps/linux/aarch64/bits/stackinfo.h new file mode 100644 index 000000000..78f326203 --- /dev/null +++ b/libc/sysdeps/linux/aarch64/bits/stackinfo.h @@ -0,0 +1,33 @@ +/* Copyright (C) 2001-2016 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 + <http://www.gnu.org/licenses/>. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +#include <elf.h> + +/* On AArch64 the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +/* Default to a non-executable stack. */ +#define DEFAULT_STACK_PERMS (PF_R|PF_W) + +#endif /* stackinfo.h */ diff --git a/libc/sysdeps/linux/aarch64/bits/syscalls.h b/libc/sysdeps/linux/aarch64/bits/syscalls.h new file mode 100644 index 000000000..3c0d840ea --- /dev/null +++ b/libc/sysdeps/linux/aarch64/bits/syscalls.h @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2016 by Waldemar Brodkorb <wbx@uclibc-ng.org> + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * ported from GNU libc + */ + +/* Copyright (C) 2005-2016 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 +<http://www.gnu.org/licenses/>. */ + +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead." +#endif + +#ifndef __ASSEMBLER__ +#include <errno.h> + +#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ + ({ long _sys_result; \ + { \ + register long _x8 __asm__ ("x8"); \ + LOAD_ARGS_##nr (args) \ + _x8 = (name); \ + \ + __asm__ volatile ( \ + "svc 0 // syscall " # name \ + : "=r" (_x0) : "r"(_x8) ASM_ARGS_##nr \ + : "memory"); \ + \ + _sys_result = _x0; \ + } \ + _sys_result; }) + +/* Macros for setting up inline __asm__ input regs */ +# define ASM_ARGS_0 +# define ASM_ARGS_1 , "r" (_x0) +# define ASM_ARGS_2 ASM_ARGS_1, "r" (_x1) +# define ASM_ARGS_3 ASM_ARGS_2, "r" (_x2) +# define ASM_ARGS_4 ASM_ARGS_3, "r" (_x3) +# define ASM_ARGS_5 ASM_ARGS_4, "r" (_x4) +# define ASM_ARGS_6 ASM_ARGS_5, "r" (_x5) +# define ASM_ARGS_7 ASM_ARGS_6, "r" (_x6) + +/* Macros for converting sys-call wrapper args into sys call args */ +# define LOAD_ARGS_0() \ + register long _x0 __asm__ ("x0"); +# define LOAD_ARGS_1(x0) \ + long _x0tmp; \ + LOAD_ARGS_0 () \ + _x0tmp = (long) (x0); \ + _x0 = _x0tmp; +# define LOAD_ARGS_2(x0, x1) \ + register long _x1 __asm__ ("x1"); \ + long _x1tmp; \ + LOAD_ARGS_1 (x0) \ + _x1tmp = (long) (x1); \ + _x1 = _x1tmp; +# define LOAD_ARGS_3(x0, x1, x2) \ + register long _x2 __asm__ ("x2"); \ + long _x2tmp; \ + LOAD_ARGS_2 (x0, x1) \ + _x2tmp = (long) (x2); \ + _x2 = _x2tmp; +# define LOAD_ARGS_4(x0, x1, x2, x3) \ + register long _x3 __asm__ ("x3"); \ + long _x3tmp; \ + LOAD_ARGS_3 (x0, x1, x2) \ + _x3tmp = (long) (x3); \ + _x3 = _x3tmp; +# define LOAD_ARGS_5(x0, x1, x2, x3, x4) \ + register long _x4 __asm__ ("x4"); \ + long _x4tmp; \ + LOAD_ARGS_4 (x0, x1, x2, x3) \ + _x4tmp = (long) (x4); \ + _x4 = _x4tmp; +# define LOAD_ARGS_6(x0, x1, x2, x3, x4, x5) \ + register long _x5 __asm__ ("x5"); \ + long _x5tmp; \ + LOAD_ARGS_5 (x0, x1, x2, x3, x4) \ + _x5tmp = (long) (x5); \ + _x5 = _x5tmp; +# define LOAD_ARGS_7(x0, x1, x2, x3, x4, x5, x6)\ + register long _x6 __asm__ ("x6"); \ + long _x6tmp; \ + LOAD_ARGS_6 (x0, x1, x2, x3, x4, x5) \ + _x6tmp = (long) (x6); \ + _x6 = _x6tmp; + +#endif /* ! __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/libc/sysdeps/linux/aarch64/bits/uClibc_arch_features.h b/libc/sysdeps/linux/aarch64/bits/uClibc_arch_features.h new file mode 100644 index 000000000..7cae090ec --- /dev/null +++ b/libc/sysdeps/linux/aarch64/bits/uClibc_arch_features.h @@ -0,0 +1,38 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#define __UCLIBC_ABORT_INSTRUCTION__ "bl abort" + +/* can your target use syscall6() for mmap ? */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target have a broken create_module() ? */ +#define __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* define if target supports CFI pseudo ops */ +#define __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* only weird assemblers generally need this */ +#undef __UCLIBC_ASM_LINE_SEP__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/aarch64/bits/uClibc_page.h b/libc/sysdeps/linux/aarch64/bits/uClibc_page.h new file mode 100755 index 000000000..4f92abcf8 --- /dev/null +++ b/libc/sysdeps/linux/aarch64/bits/uClibc_page.h @@ -0,0 +1,25 @@ +/* + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + */ + +#ifndef _UCLIBC_PAGE_H +#define _UCLIBC_PAGE_H + +/* + * AARCH64 supports 4k, 16k, 64k pages (build time). + */ + +#include <features.h> + +#if defined(__CONFIG_AARCH64_PAGE_SIZE_64K__) +#define PAGE_SHIFT 16 +#elif defined(__CONFIG_AARCH64_PAGE_SIZE_16K__) +#define PAGE_SHIFT 14 +#else +#define PAGE_SHIFT 12 +#endif + +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#endif /* _UCLIBC_PAGE_H */ diff --git a/libc/sysdeps/linux/aarch64/bits/wordsize.h b/libc/sysdeps/linux/aarch64/bits/wordsize.h new file mode 100644 index 000000000..0944f9e26 --- /dev/null +++ b/libc/sysdeps/linux/aarch64/bits/wordsize.h @@ -0,0 +1,18 @@ +/* Copyright (C) 1999-2016 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 + <http://www.gnu.org/licenses/>. */ + +#define __WORDSIZE 64 diff --git a/libc/sysdeps/linux/aarch64/bsd-_setjmp.S b/libc/sysdeps/linux/aarch64/bsd-_setjmp.S new file mode 100644 index 000000000..4e6a2da56 --- /dev/null +++ b/libc/sysdeps/linux/aarch64/bsd-_setjmp.S @@ -0,0 +1 @@ +/* _setjmp is in setjmp.S */ diff --git a/libc/sysdeps/linux/aarch64/bsd-setjmp.S b/libc/sysdeps/linux/aarch64/bsd-setjmp.S new file mode 100644 index 000000000..1da848d2f --- /dev/null +++ b/libc/sysdeps/linux/aarch64/bsd-setjmp.S @@ -0,0 +1 @@ +/* setjmp is in setjmp.S */ diff --git a/libc/sysdeps/linux/aarch64/clone.S b/libc/sysdeps/linux/aarch64/clone.S new file mode 100644 index 000000000..7437eec8d --- /dev/null +++ b/libc/sysdeps/linux/aarch64/clone.S @@ -0,0 +1,85 @@ +/* Copyright (C) 1996-2017 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 + <http://www.gnu.org/licenses/>. */ + +/* 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 <sysdep.h> +#define _ERRNO_H 1 +#include <bits/errno.h> + +#define CLONE_VM_BIT 8 +#define CLONE_VM (1 << CLONE_VM_BIT) + +#define CLONE_THREAD_BIT 16 +#define CLONE_THREAD (1 << CLONE_THREAD_BIT) + +/* int clone(int (*fn)(void *arg), x0 + void *child_stack, x1 + int flags, x2 + void *arg, x3 + pid_t *ptid, x4 + struct user_desc *tls, x5 + pid_t *ctid); x6 + */ + .text +ENTRY(__clone) + /* Save args for the child. */ + mov x10, x0 + mov x11, x2 + mov x12, x3 + + /* Sanity check args. */ + mov x0, #-EINVAL + cbz x10, .Lsyscall_error + cbz x1, .Lsyscall_error + + /* Do the system call. */ + /* X0:flags, x1:newsp, x2:parenttidptr, x3:newtls, x4:childtid. */ + mov x0, x2 /* flags */ + /* New sp is already in x1. */ + mov x2, x4 /* ptid */ + mov x3, x5 /* tls */ + mov x4, x6 /* ctid */ + mov x8, #SYS_ify(clone) + svc 0x0 + + cmp x0, #0 + beq thread_start + blt .Lsyscall_error + RET +PSEUDO_END (__clone) + + .align 4 + .type thread_start, %function +thread_start: + cfi_startproc + cfi_undefined (x30) + mov x29, 0 + + /* Pick the function arg and execute. */ + mov x0, x12 + blr x10 + + /* We are done, pass the return value through x0. */ + b HIDDEN_JUMPTARGET(_exit) + cfi_endproc + .size thread_start, .-thread_start + +libc_hidden_def (__clone) +weak_alias (__clone, clone) diff --git a/libc/sysdeps/linux/aarch64/crt1.S b/libc/sysdeps/linux/aarch64/crt1.S new file mode 100644 index 000000000..09d0327ac --- /dev/null +++ b/libc/sysdeps/linux/aarch64/crt1.S @@ -0,0 +1,89 @@ +/* Copyright (C) 1995-2016 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 + <http://www.gnu.org/licenses/>. */ + +/* This is the canonical entry point, usually the first thing in the text + segment. + + Note that the code in the .init section has already been run. + This includes _init and _libc_init + + + At this entry point, most registers' values are unspecified, except: + + x0 Contains a function pointer to be registered with `atexit'. + This is how the dynamic linker arranges to have DT_FINI + functions called for shared libraries that have been loaded + before this code runs. + + sp The stack contains the arguments and environment: + 0(sp) argc + 8(sp) argv[0] + ... + (8*argc)(sp) NULL + (8*(argc+1))(sp) envp[0] + ... + NULL + */ + + .text + .globl _start + .type _start,#function +_start: + /* Create an initial frame with 0 LR and FP */ + mov x29, #0 + mov x30, #0 + + /* Setup _fini in argument register */ + mov x5, x0 + + /* Load argc and a pointer to argv */ + ldr x1, [sp, #0] + add x2, sp, #8 + + /* Setup stack limit in argument register */ + mov x6, sp + +#ifdef __PIC__ + adrp x0, :got:main + ldr x0, [x0, #:got_lo12:main] + + adrp x3, :got:_init + ldr x3, [x3, #:got_lo12:_init] + + adrp x4, :got:_fini + ldr x4, [x4, #:got_lo12:_fini] +#else + /* Set up the other arguments in registers */ + ldr x0, =main + ldr x3, =_init + ldr x4, =_fini +#endif + + /* Let the libc call main and exit with its return code. */ + bl __uClibc_main + + /* should never get here....*/ + bl abort + + /* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start diff --git a/libc/sysdeps/linux/aarch64/crti.S b/libc/sysdeps/linux/aarch64/crti.S new file mode 100644 index 000000000..49c57e4c4 --- /dev/null +++ b/libc/sysdeps/linux/aarch64/crti.S @@ -0,0 +1,59 @@ +/* Special .init and .fini section support for AArch64. + Copyright (C) 1995-2016 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + 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 + <http://www.gnu.org/licenses/>. */ + +/* crti.S puts a function prologue at the beginning of the .init and + .fini sections and defines global symbols for those addresses, so + they can be called as functions. The symbols _init and _fini are + magic and cause the linker to emit DT_INIT and DT_FINI. */ + +#include <libc-symbols.h> + + + .section .init,"ax",%progbits + .align 2 + .global _init + .type _init, %function +_init: + stp x29, x30, [sp, -16]! + mov x29, sp + + .section .fini,"ax",%progbits + .align 2 + .global _fini + .type _fini, %function +_fini: + stp x29, x30, [sp, -16]! + mov x29, sp diff --git a/libc/sysdeps/linux/aarch64/crtn.S b/libc/sysdeps/linux/aarch64/crtn.S new file mode 100644 index 000000000..33d5f3d82 --- /dev/null +++ b/libc/sysdeps/linux/aarch64/crtn.S @@ -0,0 +1,46 @@ +/* Special .init and .fini section support for AArch64. + Copyright (C) 1995-2016 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + 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 + <http://www.gnu.org/licenses/>. */ + +/* crtn.S puts function epilogues in the .init and .fini sections + corresponding to the prologues in crti.S. */ + + .section .init,"ax",%progbits + ldp x29, x30, [sp], 16 + RET + + .section .fini,"ax",%progbits + ldp x29, x30, [sp], 16 + RET diff --git a/libc/sysdeps/linux/aarch64/jmpbuf-offsets.h b/libc/sysdeps/linux/aarch64/jmpbuf-offsets.h new file mode 100644 index 000000000..ab00cef26 --- /dev/null +++ b/libc/sysdeps/linux/aarch64/jmpbuf-offsets.h @@ -0,0 +1,57 @@ +/* Copyright (C) 2006-2016 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 + <http://www.gnu.org/licenses/>. */ + +#define JB_X19 0 +#define JB_X20 1 +#define JB_X21 2 +#define JB_X22 3 +#define JB_X23 4 +#define JB_X24 5 +#define JB_X25 6 +#define JB_X26 7 +#define JB_X27 8 +#define JB_X28 9 +#define JB_X29 10 +#define JB_LR 11 +#define JB_SP 13 + +#define JB_D8 14 +#define JB_D9 15 +#define JB_D10 16 +#define JB_D11 17 +#define JB_D12 18 +#define JB_D13 19 +#define JB_D14 20 +#define JB_D15 21 + +#ifndef __ASSEMBLER__ +#include <setjmp.h> +#include <stdint.h> +#include <sysdep.h> + +static inline uintptr_t __attribute__ ((unused)) +_jmpbuf_sp (__jmp_buf jmpbuf) +{ + uintptr_t sp = jmpbuf[JB_SP]; + return sp; +} +#endif + +/* Helper for generic ____longjmp_chk(). */ +#define JB_FRAME_ADDRESS(buf) \ + ((void *) _jmpbuf_sp (buf)) diff --git a/libc/sysdeps/linux/aarch64/jmpbuf-unwind.h b/libc/sysdeps/linux/aarch64/jmpbuf-unwind.h new file mode 100644 index 000000000..77bad1d41 --- /dev/null +++ b/libc/sysdeps/linux/aarch64/jmpbuf-unwind.h @@ -0,0 +1,34 @@ +/* Copyright (C) 2005-2016 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 + <http://www.gnu.org/licenses/>. */ + +#include <setjmp.h> +#include <jmpbuf-offsets.h> +#include <stdint.h> +#include <unwind.h> + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address, demangle) \ + ((void *) (address) < (void *) demangle (jmpbuf[JB_SP])) + +#define _JMPBUF_CFA_UNWINDS_ADJ(jmpbuf, context, adj) \ + _JMPBUF_UNWINDS_ADJ (jmpbuf, (void *) _Unwind_GetCFA (context), adj) + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ + ((uintptr_t) (_address) - (_adj) < _jmpbuf_sp (_jmpbuf) - (_adj)) + diff --git a/libc/sysdeps/linux/aarch64/setjmp.S b/libc/sysdeps/linux/aarch64/setjmp.S new file mode 100644 index 000000000..b3d616222 --- /dev/null +++ b/libc/sysdeps/linux/aarch64/setjmp.S @@ -0,0 +1,59 @@ +/* Copyright (C) 1997-2016 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 + <http://www.gnu.org/licenses/>. */ + +#include <sysdep.h> +#include <jmpbuf-offsets.h> + + /* Keep traditional entry points in with sigsetjmp(). */ +ENTRY (setjmp) + mov x1, #1 + b 1f +END (setjmp) + +ENTRY (_setjmp) + mov x1, #0 + b 1f +END (_setjmp) +libc_hidden_def (_setjmp) + +ENTRY (__sigsetjmp) + +1: + stp x19, x20, [x0, #JB_X19<<3] + stp x21, x22, [x0, #JB_X21<<3] + stp x23, x24, [x0, #JB_X23<<3] + stp x25, x26, [x0, #JB_X25<<3] + stp x27, x28, [x0, #JB_X27<<3] + + stp x29, x30, [x0, #JB_X29<<3] + + /* setjmp probe takes 3 arguments, address of jump buffer + first argument (8@x0), return value second argument (-4@x1), + and target address (8@x30), respectively. */ + //LIBC_PROBE (setjmp, 3, 8@x0, -4@x1, 8@x30) + stp d8, d9, [x0, #JB_D8<<3] + stp d10, d11, [x0, #JB_D10<<3] + stp d12, d13, [x0, #JB_D12<<3] + stp d14, d15, [x0, #JB_D14<<3] + mov x2, sp + str x2, [x0, #JB_SP<<3] + + b C_SYMBOL_NAME(__sigjmp_save) + +END (__sigsetjmp) +hidden_def (__sigsetjmp) diff --git a/libc/sysdeps/linux/aarch64/sys/procfs.h b/libc/sysdeps/linux/aarch64/sys/procfs.h new file mode 100644 index 000000000..7e408c3f8 --- /dev/null +++ b/libc/sysdeps/linux/aarch64/sys/procfs.h @@ -0,0 +1,123 @@ +/* Copyright (C) 1996-2016 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 + <http://www.gnu.org/licenses/>. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include <features.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/user.h> + +__BEGIN_DECLS + +/* Type for a general-purpose register. */ +typedef unsigned long elf_greg_t; + +/* And the whole bunch of them. We could have used `struct + pt_regs' directly in the typedef, but tradition says that + the register set is an array, which does have some peculiar + semantics, so leave it that way. */ +#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Register set for the floating-point registers. */ +typedef struct user_fpsimd_struct elf_fpregset_t; + +/* Signal info. */ +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with Linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + GDB doesn't really use excluded. */ + +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args. */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned int pr_uid; + unsigned int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +/* The rest of this file provides the types for emulation of the + Solaris <proc_service.h> interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/libc/sysdeps/linux/aarch64/sys/ucontext.h b/libc/sysdeps/linux/aarch64/sys/ucontext.h new file mode 100644 index 000000000..d17458896 --- /dev/null +++ b/libc/sysdeps/linux/aarch64/sys/ucontext.h @@ -0,0 +1,53 @@ +/* Copyright (C) 1998-2016 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 + <http://www.gnu.org/licenses/>. */ + +/* System V/AArch64 ABI compliant context switching support. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include <features.h> +#include <signal.h> + +#include <sys/procfs.h> + +typedef elf_greg_t greg_t; + +/* Container for all general registers. */ +typedef elf_gregset_t gregset_t; + +/* Structure to describe FPU registers. */ +typedef elf_fpregset_t fpregset_t; + +/* Context to describe whole processor state. This only describes + the core registers; coprocessor registers get saved elsewhere + (e.g. in uc_regspace, or somewhere unspecified on the stack + during non-RT signal handlers). */ +typedef struct sigcontext mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + __sigset_t uc_sigmask; + mcontext_t uc_mcontext; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/libc/sysdeps/linux/aarch64/sys/user.h b/libc/sysdeps/linux/aarch64/sys/user.h new file mode 100644 index 000000000..f6fc361e8 --- /dev/null +++ b/libc/sysdeps/linux/aarch64/sys/user.h @@ -0,0 +1,37 @@ +/* Copyright (C) 2009-2016 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 + <http://www.gnu.org/licenses/>. */ + +#ifndef _SYS_USER_H +#define _SYS_USER_H 1 + +struct user_regs_struct +{ + unsigned long long regs[31]; + unsigned long long sp; + unsigned long long pc; + unsigned long long pstate; +}; + +struct user_fpsimd_struct +{ + __uint128_t vregs[32]; + unsigned int fpsr; + unsigned int fpcr; +}; + +#endif diff --git a/libc/sysdeps/linux/aarch64/syscall.S b/libc/sysdeps/linux/aarch64/syscall.S new file mode 100644 index 000000000..ac609a337 --- /dev/null +++ b/libc/sysdeps/linux/aarch64/syscall.S @@ -0,0 +1,42 @@ +/* Copyright (C) 2005-2017 Free Software Foundation, Inc. + + 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 + <http://www.gnu.org/licenses/>. */ + +#include <sysdep.h> + +/* syscall (int nr, ...) + + AArch64 system calls take between 0 and 7 arguments. On entry here nr + is in w0 and any other system call arguments are in register x1..x7. + + For kernel entry we need to move the system call nr to x8 then + load the remaining arguments to register. */ + +ENTRY (syscall) + uxtw x8, w0 + mov x0, x1 + mov x1, x2 + mov x2, x3 + mov x3, x4 + mov x4, x5 + mov x5, x6 + mov x6, x7 + svc 0x0 + cmn x0, #4095 + b.cs 1f + RET +1: + b SYSCALL_ERROR +PSEUDO_END (syscall) diff --git a/libc/sysdeps/linux/aarch64/sysdep.h b/libc/sysdeps/linux/aarch64/sysdep.h new file mode 100644 index 000000000..82790be6d --- /dev/null +++ b/libc/sysdeps/linux/aarch64/sysdep.h @@ -0,0 +1,150 @@ +/* Copyright (C) 2005-2016 Free Software Foundation, Inc. + +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 +<http://www.gnu.org/licenses/>. */ + +#ifndef _LINUX_AARCH64_SYSDEP_H +#define _LINUX_AARCH64_SYSDEP_H 1 + +#include <common/sysdep.h> +#include <sys/syscall.h> + +/* In order to get __set_errno() definition in INLINE_SYSCALL. */ +#ifndef __ASSEMBLER__ +#include <errno.h> +#endif + +/* 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) + +#ifdef __ASSEMBLER__ + +#define ASM_SIZE_DIRECTIVE(name) .size name,.-name + +/* Local label name for asm code. */ +#ifndef L +# define L(name) .L##name +#endif + +/* Define an entry point visible from C. */ +#define ENTRY(name) \ + .globl C_SYMBOL_NAME(name); \ + .type C_SYMBOL_NAME(name),%function; \ + .align 4; \ + C_LABEL(name) \ + cfi_startproc; + +/* Define an entry point visible from C. */ +#define ENTRY_ALIGN(name, align) \ + .globl C_SYMBOL_NAME(name); \ + .type C_SYMBOL_NAME(name),%function; \ + .p2align align; \ + C_LABEL(name) \ + cfi_startproc; + +#undef END +#define END(name) \ + cfi_endproc; \ + ASM_SIZE_DIRECTIVE(name) + +/* Linux uses a negative return value to indicate syscall errors, +unlike most Unices, which use the condition codes' carry flag. + +Since version 2.1 the return value of a system call might be +negative even if the call succeeded. E.g., the `lseek' system call +might return a large offset. Therefore we must not anymore test +for < 0, but test for a real error by making sure the value in R0 +is a real error number. Linus said he will make sure the no syscall +returns a value in -1 .. -4095 as a valid result so we can safely +test with -4095. */ + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ +.text; \ +ENTRY (name); \ +DO_CALL (syscall_name, args); \ +cmn x0, #4095; \ +b.cs .Lsyscall_error; + +# undef PSEUDO_END +# define PSEUDO_END(name) \ +SYSCALL_ERROR_HANDLER \ +END (name) + +# undef PSEUDO_NOERRNO +# define PSEUDO_NOERRNO(name, syscall_name, args) \ +.text; \ +ENTRY (name); \ +DO_CALL (syscall_name, args); + +# undef PSEUDO_END_NOERRNO +# define PSEUDO_END_NOERRNO(name) \ +END (name) + +# define ret_NOERRNO ret + +/* The function has to return the error code. */ +# undef PSEUDO_ERRVAL +# define PSEUDO_ERRVAL(name, syscall_name, args) \ +.text; \ +ENTRY (name) \ +DO_CALL (syscall_name, args); \ +neg x0, x0 + +# undef PSEUDO_END_ERRVAL +# define PSEUDO_END_ERRVAL(name) \ +END (name) + +# define ret_ERRVAL ret + +#if defined _LIBC_REENTRANT +# if defined USE___THREAD +# ifndef NOT_IN_libc +# define SYSCALL_ERROR_ERRNO __libc_errno +# else +# define SYSCALL_ERROR_ERRNO errno +# endif +# endif +#endif + +#if defined USE___THREAD +# define SYSCALL_ERROR .Lsyscall_error +# define SYSCALL_ERROR_HANDLER \ +.Lsyscall_error: \ + adrp x1, :gottprel:SYSCALL_ERROR_ERRNO; \ + neg w2, w0; \ + ldr x1, [x1, :gottprel_lo12:SYSCALL_ERROR_ERRNO]; \ + mrs x3, tpidr_el0; \ + mov x0, -1; \ + str w2, [x1, x3]; \ + ret; +#else +# define SYSCALL_ERROR __syscall_error +# define SYSCALL_ERROR_HANDLER \ +.Lsyscall_error: \ + b __syscall_error; +#endif + +# undef DO_CALL +# define DO_CALL(syscall_name, args) \ +mov x8, SYS_ify (syscall_name); \ +svc 0 + +#endif /* __ASSEMBLER__ */ + +#endif /* linux/aarch64/sysdep.h */ diff --git a/libc/sysdeps/linux/aarch64/vfork.S b/libc/sysdeps/linux/aarch64/vfork.S new file mode 100644 index 000000000..9a8fd469a --- /dev/null +++ b/libc/sysdeps/linux/aarch64/vfork.S @@ -0,0 +1,37 @@ +/* Copyright (C) 1999-2017 Free Software Foundation, Inc. + + 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 + <http://www.gnu.org/licenses/>. */ + +#include <sysdep.h> +#define _ERRNO_H 1 +#include <bits/errno.h> + +/* 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) + + mov x0, #0x4111 /* CLONE_VM | CLONE_VFORK | SIGCHLD */ + mov x1, sp + DO_CALL (clone, 2) + + cmn x0, #4095 + b.cs .Lsyscall_error + RET + +PSEUDO_END (vfork) +libc_hidden_def (vfork) diff --git a/libc/sysdeps/linux/common-generic/bits/stat.h b/libc/sysdeps/linux/common-generic/bits/stat.h index 945c408a0..0f66fc0e7 100644 --- a/libc/sysdeps/linux/common-generic/bits/stat.h +++ b/libc/sysdeps/linux/common-generic/bits/stat.h @@ -30,45 +30,6 @@ */ struct stat { -#ifndef __USE_FILE_OFFSET64 -# if __BYTE_ORDER == __LITTLE_ENDIAN - unsigned long st_dev; /* Device. */ - unsigned long __pad1; - unsigned long st_ino; /* 32bit file serial number. */ - unsigned long __pad2; - unsigned int st_mode; /* File mode. */ - unsigned int st_nlink; /* Link count. */ - unsigned int st_uid; /* User ID of the file's owner. */ - unsigned int st_gid; /* Group ID of the file's group.*/ - unsigned long st_rdev; /* Device number, if device. */ - unsigned long __pad3; - unsigned long long __pad4; - long st_size; /* SIze of file, in bytes. */ - long __pad5; - int st_blksize; /* Optimal block size for I/O. */ - int __pad6; - long st_blocks; /* Number 512-byte blocks allocated */ - long __pad7; -# else - unsigned long __pad1; - unsigned long st_dev; /* Device. */ - unsigned long __pad2; - unsigned long st_ino; /* 32bit file serial number. */ - unsigned int st_mode; /* File mode. */ - unsigned int st_nlink; /* Link count. */ - unsigned int st_uid; /* User ID of the file's owner. */ - unsigned int st_gid; /* Group ID of the file's group.*/ - unsigned long __pad3; - unsigned long st_rdev; /* Device number, if device. */ - unsigned long long __pad4; - long __pad5; - long st_size; /* Size of file, in bytes. */ - int st_blksize; /* Optimal block size for I/O. */ - int __pad6; - long __pad7; - long st_blocks; /* Number 512-byte blocks allocated */ -# endif /* __LITTLE_ENDIAN */ -#else unsigned long long st_dev; /* Device. */ unsigned long long st_ino; /* 32bit file serial number. */ unsigned int st_mode; /* File mode. */ @@ -81,7 +42,6 @@ struct stat int st_blksize; /* Optimal block size for I/O. */ int __pad2; long long st_blocks; /* Number 512-byte blocks allocated */ -#endif #ifdef __USE_MISC /* Nanosecond resolution timestamps are stored in a format equivalent to 'struct timespec'. This is the type used @@ -96,21 +56,12 @@ struct stat # define st_mtime st_mtim.tv_sec # define st_ctime st_ctim.tv_sec #else -# ifndef __USE_FILE_OFFSET64 - long st_atime; /* Time of last access. */ - unsigned long st_atime_nsec; - long st_mtime; /* Time of last modification. */ - unsigned long st_mtime_nsec; - long st_ctime; /* Time of last status change. */ - unsigned long st_ctime_nsec; -# else int st_atime; /* Time of last access. */ unsigned int st_atime_nsec; int st_mtime; /* Time of last modification. */ unsigned int st_mtime_nsec; int st_ctime; /* Time of last status change. */ unsigned int st_ctime_nsec; -# endif #endif unsigned int __unused4; unsigned int __unused5; diff --git a/libc/sysdeps/linux/common/fstat.c b/libc/sysdeps/linux/common/fstat.c index eae3c8006..ac77eb295 100644 --- a/libc/sysdeps/linux/common/fstat.c +++ b/libc/sysdeps/linux/common/fstat.c @@ -7,25 +7,26 @@ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. */ -#include <sys/syscall.h> +#include <features.h> #include <unistd.h> #include <sys/stat.h> +#include <sys/syscall.h> + #include "xstatconv.h" #if defined __NR_fstat64 && !defined __NR_fstat int fstat(int fd, struct stat *buf) { - int result = INLINE_SYSCALL(fstat64, 2, fd, buf); - if (result == 0) { - /* Did we overflow? */ - if (buf->__pad1 || buf->__pad2 || buf->__pad3 - || buf->__pad4 || buf->__pad5 - || buf->__pad6 || buf->__pad7) { - __set_errno(EOVERFLOW); - return -1; - } - } - return result; + return INLINE_SYSCALL(fstat64, 2, fd, buf); +} +libc_hidden_def(fstat) + +#elif __WORDSIZE == 64 && defined __NR_newfstatat +#include <fcntl.h> + +int fstat(int fd, struct stat *buf) +{ + return INLINE_SYSCALL(fstat, 2, fd, buf); } libc_hidden_def(fstat) @@ -55,10 +56,9 @@ int fstat(int fd, struct stat *buf) return result; } libc_hidden_def(fstat) +#endif # if ! defined __NR_fstat64 strong_alias_untyped(fstat,fstat64) libc_hidden_def(fstat64) -# endif - #endif diff --git a/libc/sysdeps/linux/common/fstatat.c b/libc/sysdeps/linux/common/fstatat.c index 4006814f0..13673d76c 100644 --- a/libc/sysdeps/linux/common/fstatat.c +++ b/libc/sysdeps/linux/common/fstatat.c @@ -26,15 +26,6 @@ int fstatat(int fd, const char *file, struct stat *buf, int flag) __xstat32_conv(&kbuf, buf); # else ret = INLINE_SYSCALL(fstatat64, 4, fd, file, buf, flag); - if (ret == 0) { - /* Did we overflow */ - if (buf->__pad1 || buf->__pad2 || buf->__pad3 - || buf->__pad4 || buf->__pad5 || buf->__pad6 - || buf->__pad7) { - __set_errno(EOVERFLOW); - return -1; - } - } # endif /* __ARCH_HAS_DEPRECATED_SYSCALLS__ */ return ret; } diff --git a/libc/sysdeps/linux/common/lstat.c b/libc/sysdeps/linux/common/lstat.c index 143cc1916..cef9b463d 100644 --- a/libc/sysdeps/linux/common/lstat.c +++ b/libc/sysdeps/linux/common/lstat.c @@ -20,6 +20,15 @@ int lstat(const char *file_name, struct stat *buf) } libc_hidden_def(lstat) +#elif __WORDSIZE == 64 && defined __NR_newfstatat +# include <fcntl.h> + +int lstat(const char *file_name, struct stat *buf) +{ + return fstatat(AT_FDCWD, file_name, buf, AT_SYMLINK_NOFOLLOW); +} +libc_hidden_def(lstat) + /* For systems which have both, prefer the old one */ #else # include "xstatconv.h" diff --git a/libc/sysdeps/linux/common/lstat64.c b/libc/sysdeps/linux/common/lstat64.c index c43e53e1d..76637b556 100644 --- a/libc/sysdeps/linux/common/lstat64.c +++ b/libc/sysdeps/linux/common/lstat64.c @@ -9,11 +9,19 @@ #include <_lfs_64.h> #include <sys/syscall.h> +#include <unistd.h> +#include <sys/stat.h> -# include <unistd.h> -# include <sys/stat.h> +#if defined __NR_fstatat64 && !defined __NR_lstat +# include <fcntl.h> + +int lstat64(const char *file_name, struct stat64 *buf) +{ + return fstatat64(AT_FDCWD, file_name, buf, AT_SYMLINK_NOFOLLOW); +} +libc_hidden_def(lstat64) -#if defined __NR_fstatat64 && !defined __NR_lstat64 +#elif __WORDSIZE == 64 && defined __NR_newfstatat # include <fcntl.h> int lstat64(const char *file_name, struct stat64 *buf) diff --git a/libc/sysdeps/linux/common/stat.c b/libc/sysdeps/linux/common/stat.c index b3c2a19ea..8e4542a74 100644 --- a/libc/sysdeps/linux/common/stat.c +++ b/libc/sysdeps/linux/common/stat.c @@ -21,6 +21,14 @@ int stat(const char *file_name, struct stat *buf) return fstatat(AT_FDCWD, file_name, buf, 0); } +#elif __WORDSIZE == 64 && defined __NR_newfstatat +# include <fcntl.h> + +int stat(const char *file_name, struct stat *buf) +{ + return fstatat64(AT_FDCWD, file_name, buf, 0); +} + #else # include "xstatconv.h" |