From 8a6ec661af2bb80504b1a37a9dae57de568a27af Mon Sep 17 00:00:00 2001 From: Claudio Fontana <claudio.fontana@huawei.com> Date: Thu, 20 Mar 2014 13:20:14 +0100 Subject: [PATCH] libc: add minimal support for AArch64 this contains still prototyped code, which if reached either hangs (setjmp, longjmp), aborts (all that requires mmu::), or implements differently (allocating with malloc instead of mmap) This is enough libc AArch64 support for reaching the end of premain. Signed-off-by: Claudio Fontana <claudio.fontana@huawei.com> --- libc/arch/aarch64/atomic.h | 38 ++++++++++++++++++++++++++++ libc/arch/aarch64/setjmp/longjmp.s | 14 ++++++++++ libc/arch/aarch64/setjmp/setjmp.s | 17 +++++++++++++ libc/{ => arch/x64}/setjmp/longjmp.s | 0 libc/{ => arch/x64}/setjmp/setjmp.s | 0 libc/build.mk | 4 +-- libc/mman.cc | 28 ++++++++++++++++++++ libc/pthread.cc | 13 ++++++++++ libc/shm.cc | 12 +++++++++ libc/string/memcpy.c | 10 ++++++++ 10 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 libc/arch/aarch64/atomic.h create mode 100644 libc/arch/aarch64/setjmp/longjmp.s create mode 100644 libc/arch/aarch64/setjmp/setjmp.s rename libc/{ => arch/x64}/setjmp/longjmp.s (100%) rename libc/{ => arch/x64}/setjmp/setjmp.s (100%) diff --git a/libc/arch/aarch64/atomic.h b/libc/arch/aarch64/atomic.h new file mode 100644 index 000000000..fd997f9d4 --- /dev/null +++ b/libc/arch/aarch64/atomic.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2014 Huawei Technologies Duesseldorf GmbH + * + * This work is open source software, licensed under the terms of the + * BSD license as described in the LICENSE file in the top-level directory. + */ + +#ifndef _INTERNAL_ATOMIC_H +#define _INTERNAL_ATOMIC_H + +#include <stdint.h> +#include <bsd/sys/cddl/compat/opensolaris/sys/types.h> +#include <machine/atomic.h> + +static inline int a_ctz_64(register uint64_t x) +{ + register uint64_t r; + __asm__ __volatile__ ("rbit %0, %0; clz %1, %0" : "+r"(x), "=r"(r)); + return r; +} + +static inline int a_ctz_l(unsigned long x) +{ + return a_ctz_64(x); +} + +static inline int a_fetch_add(volatile int *x, int v) +{ + return atomic_fetchadd_int((unsigned int *)x, (unsigned int)v); +} + +static inline void a_crash() +{ + __asm__ __volatile__( "1: msr daifset, #2; wfi; b 1b; " ::: "memory"); +} + + +#endif /* _INTERNAL_ATOMIC_H */ diff --git a/libc/arch/aarch64/setjmp/longjmp.s b/libc/arch/aarch64/setjmp/longjmp.s new file mode 100644 index 000000000..cf73028e4 --- /dev/null +++ b/libc/arch/aarch64/setjmp/longjmp.s @@ -0,0 +1,14 @@ +/* Copyright 2014 Huawei Technologies Duesseldorf GmbH + * + * This work is open source software, licensed under the terms of the + * BSD license as described in the LICENSE file in the top-level directory. + */ + +.global _longjmp +.global longjmp +.type _longjmp,@function +.type longjmp,@function +_longjmp: +longjmp: + wfi + b longjmp diff --git a/libc/arch/aarch64/setjmp/setjmp.s b/libc/arch/aarch64/setjmp/setjmp.s new file mode 100644 index 000000000..654ecb26a --- /dev/null +++ b/libc/arch/aarch64/setjmp/setjmp.s @@ -0,0 +1,17 @@ +/* Copyright 2014 Huawei Technologies Duesseldorf GmbH + * + * This work is open source software, licensed under the terms of the + * BSD license as described in the LICENSE file in the top-level directory. + */ + +.global __setjmp +.global _setjmp +.global setjmp +.type __setjmp,@function +.type _setjmp,@function +.type setjmp,@function +__setjmp: +_setjmp: +setjmp: + wfi + b setjmp diff --git a/libc/setjmp/longjmp.s b/libc/arch/x64/setjmp/longjmp.s similarity index 100% rename from libc/setjmp/longjmp.s rename to libc/arch/x64/setjmp/longjmp.s diff --git a/libc/setjmp/setjmp.s b/libc/arch/x64/setjmp/setjmp.s similarity index 100% rename from libc/setjmp/setjmp.s rename to libc/arch/x64/setjmp/setjmp.s diff --git a/libc/build.mk b/libc/build.mk index 2f6f1af87..e906e4e76 100644 --- a/libc/build.mk +++ b/libc/build.mk @@ -380,8 +380,8 @@ libc += network/if_indextoname.o libc += prng/rand.o libc += prng/random.o -libc += setjmp/setjmp.o -libc += setjmp/longjmp.o +libc += arch/$(arch)/setjmp/setjmp.o +libc += arch/$(arch)/setjmp/longjmp.o libc += signal/sigrtmax.o libc += signal/sigrtmin.o diff --git a/libc/mman.cc b/libc/mman.cc index 8a9eed84e..59ef46dbd 100644 --- a/libc/mman.cc +++ b/libc/mman.cc @@ -57,6 +57,9 @@ unsigned libc_prot_to_perm(int prot) int mprotect(void *addr, size_t len, int prot) { +#ifdef AARCH64_PORT_STUB + abort(); +#else /* !AARCH64_PORT_STUB */ // we don't support mprotecting() the linear map (e.g.., malloc() memory) // because that could leave the linear map a mess. if (reinterpret_cast<long>(addr) < 0) { @@ -70,10 +73,14 @@ int mprotect(void *addr, size_t len, int prot) } return mmu::mprotect(addr, len, libc_prot_to_perm(prot)).to_libc(); +#endif /* !AARCH64_PORT_STUB */ } int mmap_validate(void *addr, size_t length, int flags, off_t offset) { +#ifdef AARCH64_PORT_STUB + abort(); +#else /* !AARCH64_PORT_STUB */ int type = flags & (MAP_SHARED|MAP_PRIVATE); // Either MAP_SHARED or MAP_PRIVATE must be set, but not both. if (!type || type == (MAP_SHARED|MAP_PRIVATE)) { @@ -84,11 +91,15 @@ int mmap_validate(void *addr, size_t length, int flags, off_t offset) return EINVAL; } return 0; +#endif /* !AARCH64_PORT_STUB */ } void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) { +#ifdef AARCH64_PORT_STUB + abort(); +#else /* !AARCH64_PORT_STUB */ trace_memory_mmap(addr, length, prot, flags, fd, offset); int err = mmap_validate(addr, length, flags, offset); @@ -125,6 +136,7 @@ void *mmap(void *addr, size_t length, int prot, int flags, } trace_memory_mmap_ret(ret); return ret; +#endif /* !AARCH64_PORT_STUB */ } extern "C" void *mmap64(void *addr, size_t length, int prot, int flags, @@ -134,14 +146,21 @@ extern "C" void *mmap64(void *addr, size_t length, int prot, int flags, int munmap_validate(void *addr, size_t length) { +#ifdef AARCH64_PORT_STUB + abort(); +#else /* !AARCH64_PORT_STUB */ if (!mmu::is_page_aligned(addr) || length == 0) { return EINVAL; } return 0; +#endif /* !AARCH64_PORT_STUB */ } int munmap(void *addr, size_t length) { +#ifdef AARCH64_PORT_STUB + abort(); +#else /* !AARCH64_PORT_STUB */ trace_memory_munmap(addr, length); int error = munmap_validate(addr, length); if (error) { @@ -155,18 +174,27 @@ int munmap(void *addr, size_t length) } trace_memory_munmap_ret(); return ret; +#endif /* !AARCH64_PORT_STUB */ } int msync(void *addr, size_t length, int flags) { +#ifdef AARCH64_PORT_STUB + abort(); +#else /* !AARCH64_PORT_STUB */ return mmu::msync(addr, length, flags).to_libc(); +#endif /* !AARCH64_PORT_STUB */ } int mincore(void *addr, size_t length, unsigned char *vec) { +#ifdef AARCH64_PORT_STUB + abort(); +#else /* !AARCH64_PORT_STUB */ if (!mmu::is_page_aligned(addr)) { return libc_error(EINVAL); } return mmu::mincore(addr, length, vec).to_libc(); +#endif /* !AARCH64_PORT_STUB */ } diff --git a/libc/pthread.cc b/libc/pthread.cc index 4e594b240..abfdabb2a 100644 --- a/libc/pthread.cc +++ b/libc/pthread.cc @@ -14,7 +14,11 @@ #include <algorithm> #include <string.h> #include <list> + +#ifndef AARCH64_PORT_STUB #include <osv/mmu.hh> +#endif /* !AARCH64_PORT_STUB */ + #include <osv/debug.hh> #include <osv/prio.hh> @@ -90,8 +94,13 @@ namespace pthread_private { return {attr.stack_begin, attr.stack_size}; } size_t size = attr.stack_size; +#ifdef AARCH64_PORT_STUB + size = (size + (0xfff)) & (~0xfffull); + void *addr = malloc(size); +#else /* !AARCH64_PORT_STUB */ void *addr = mmu::map_anon(nullptr, size, mmu::mmap_populate, mmu::perm_rw); mmu::mprotect(addr, attr.guard_size, 0); +#endif /* !AARCH64_PORT_STUB */ sched::thread::stack_info si{addr, size}; si.deleter = free_stack; return si; @@ -99,7 +108,11 @@ namespace pthread_private { void pthread::free_stack(sched::thread::stack_info si) { +#ifdef AARCH64_PORT_STUB + free(si.begin); +#else /* !AARCH64_PORT_STUB */ mmu::munmap(si.begin, si.size); +#endif /* !AARCH64_PORT_STUB */ } int pthread::join(void** retval) diff --git a/libc/shm.cc b/libc/shm.cc index a3c685521..c9cdc5b58 100644 --- a/libc/shm.cc +++ b/libc/shm.cc @@ -23,6 +23,9 @@ static std::unordered_map<const void*, int> shmmap; void *shmat(int shmid, const void *shmaddr, int shmflg) { +#ifdef AARCH64_PORT_STUB + abort(); +#else /* !AARCH64_PORT_STUB */ fileref f(fileref_from_fd(shmid)); void *addr; try { @@ -36,6 +39,7 @@ void *shmat(int shmid, const void *shmaddr, int shmflg) shmmap.emplace(addr, shmid); } return addr; +#endif /* !AARCH64_PORT_STUB */ } int shmctl(int shmid, int cmd, struct shmid_ds *buf) @@ -49,6 +53,9 @@ int shmctl(int shmid, int cmd, struct shmid_ds *buf) int shmdt(const void *shmaddr) { +#ifdef AARCH64_PORT_STUB + abort(); +#else /* !AARCH64_PORT_STUB */ int fd; WITH_LOCK(shm_lock) { auto s = shmmap.find(shmaddr); @@ -61,6 +68,7 @@ int shmdt(const void *shmaddr) fileref f(fileref_from_fd(fd)); mmu::munmap(shmaddr, ::size(f)); return 0; +#endif /* !AARCH64_PORT_STUB */ } /* @@ -69,6 +77,9 @@ int shmdt(const void *shmaddr) */ int shmget(key_t key, size_t size, int shmflg) { +#ifdef AARCH64_PORT_STUB + abort(); +#else int fd; int flags = FREAD | FWRITE; size = align_up(size, mmu::page_size); @@ -96,4 +107,5 @@ int shmget(key_t key, size_t size, int shmflg) return libc_error(error); } return fd; +#endif /* !AARCH64_PORT_STUB */ } diff --git a/libc/string/memcpy.c b/libc/string/memcpy.c index 23162151f..49ea8fe36 100644 --- a/libc/string/memcpy.c +++ b/libc/string/memcpy.c @@ -27,3 +27,13 @@ misaligned: } return dest; } + +void *memcpy_base_backwards(void *__restrict dest, const void *__restrict src, size_t n) +{ + unsigned char *d = dest + n - 1; + const unsigned char *s = src + n - 1; + + for (; n; n--) *d-- = *s--; + + return dest; +} -- GitLab