From 4ec1bac77492a59369c137b20e0ee67cc204c580 Mon Sep 17 00:00:00 2001 From: Travis Geiselbrecht Date: Sun, 26 Jan 2014 22:52:16 -0800 Subject: [PATCH] [arch][arm64] initial port to armv8-a (aarch64) --- arch/arm64/arch.c | 56 ++++++++ arch/arm64/asm.S | 94 ++++++++++++ arch/arm64/exceptions.S | 175 ++++++++++++++++++++++ arch/arm64/exceptions_c.c | 73 ++++++++++ arch/arm64/include/arch/arch_ops.h | 200 ++++++++++++++++++++++++++ arch/arm64/include/arch/arch_thread.h | 30 ++++ arch/arm64/include/arch/arm64.h | 60 ++++++++ arch/arm64/include/arch/defines.h | 29 ++++ arch/arm64/rules.mk | 68 +++++++++ arch/arm64/start.S | 16 +++ arch/arm64/system-onesegment.ld | 101 +++++++++++++ arch/arm64/thread.c | 92 ++++++++++++ lib/libc/string/arch/arm64/rules.mk | 2 + 13 files changed, 996 insertions(+) create mode 100644 arch/arm64/arch.c create mode 100644 arch/arm64/asm.S create mode 100644 arch/arm64/exceptions.S create mode 100644 arch/arm64/exceptions_c.c create mode 100644 arch/arm64/include/arch/arch_ops.h create mode 100644 arch/arm64/include/arch/arch_thread.h create mode 100644 arch/arm64/include/arch/arm64.h create mode 100644 arch/arm64/include/arch/defines.h create mode 100644 arch/arm64/rules.mk create mode 100644 arch/arm64/start.S create mode 100644 arch/arm64/system-onesegment.ld create mode 100644 arch/arm64/thread.c create mode 100644 lib/libc/string/arch/arm64/rules.mk diff --git a/arch/arm64/arch.c b/arch/arm64/arch.c new file mode 100644 index 00000000..cb78dd82 --- /dev/null +++ b/arch/arm64/arch.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014 Travis Geiselbrecht + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include +#include +#include +#include +#include + +extern int _end_of_ram; +void *_heap_end = &_end_of_ram; + +void arch_early_init(void) +{ + /* set the vector base */ + ARM64_WRITE_SYSREG(VBAR_EL1, (uint64_t)&arm64_exception_base); + + /* switch to EL1 */ + unsigned int current_el = ARM64_READ_SYSREG(CURRENTEL) >> 2; + if (current_el > 1) { + arm64_el3_to_el1(); + } +} + +void arch_init(void) +{ +} + +void arch_quiesce(void) +{ +} + +void arch_idle(void) +{ + __asm__ volatile("wfi"); +} + diff --git a/arch/arm64/asm.S b/arch/arm64/asm.S new file mode 100644 index 00000000..617547d3 --- /dev/null +++ b/arch/arm64/asm.S @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2014 Travis Geiselbrecht + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include + +.macro push ra, rb +stp \ra, \rb, [sp,#-16]! +.endm + +.macro pop ra, rb +ldp \ra, \rb, [sp], #16 +.endm + +/* void arm64_context_switch(vaddr_t *old_sp, vaddr_t new_sp); */ +FUNCTION(arm64_context_switch) + /* save old frame */ + push x28, x29 + push x26, x27 + push x24, x25 + push x22, x23 + push x20, x21 + push x18, x19 + str x30, [sp,#-8]! + + /* save old sp */ + mov x15, sp + str x15, [x0] + + /* load new sp */ + mov sp, x1 + + /* restore new frame */ + ldr x30, [sp], #8 + pop x18, x19 + pop x20, x21 + pop x22, x23 + pop x24, x25 + pop x26, x27 + pop x28, x29 + + ret + +FUNCTION(arm64_el3_to_el1) + /* set EL2 to 64bit */ + mrs x0, scr_el3 + orr x0, x0, #(1<<10) + msr scr_el3, x0 + + /* set EL1 to 64bit */ + mov x0, #(1<<31) + msr hcr_el2, x0 + + /* disable EL2 coprocessor traps */ + mov x0, #0x33ff + msr cptr_el2, x0 + + /* disable EL1 FPU traps */ + mov x0, #(0b11<<20) + msr cpacr_el1, x0 + + /* set up the EL1 bounce interrupt */ + mov x0, sp + msr sp_el1, x0 + + adr x0, .Ltarget + msr elr_el3, x0 + + mov x0, #((0b1111 << 6) | (0b0101)) /* EL1h runlevel */ + msr spsr_el3, x0 + isb + + eret + +.Ltarget: + ret diff --git a/arch/arm64/exceptions.S b/arch/arm64/exceptions.S new file mode 100644 index 00000000..53c8a932 --- /dev/null +++ b/arch/arm64/exceptions.S @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2014 Travis Geiselbrecht + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include + +.section .text.boot.vectab +.align 12 + +.macro push ra, rb +stp \ra, \rb, [sp,#-16]! +.endm + +.macro pop ra, rb +ldp \ra, \rb, [sp], #16 +.endm + +#define lr x30 +#define regsave_long_offset 0xf0 + +.macro regsave_long +sub sp, sp, #32 +push x28, x29 +push x26, x27 +push x24, x25 +push x22, x23 +push x20, x21 +push x18, x19 +push x16, x17 +push x14, x15 +push x12, x13 +push x10, x11 +push x8, x9 +push x6, x7 +push x4, x5 +push x2, x3 +push x0, x1 +add x0, sp, #regsave_long_offset +mrs x1, elr_el1 +mrs x2, spsr_el1 +stp lr, x0, [sp, #regsave_long_offset] +stp x1, x2, [sp, #regsave_long_offset + 16] +.endm + +.macro regrestore_long +ldr lr, [sp, #regsave_long_offset] +ldp x1, x2, [sp, #regsave_long_offset + 16] +msr elr_el1, x1 +msr spsr_el1, x2 +pop x0, x1 +pop x2, x3 +pop x4, x5 +pop x6, x7 +pop x8, x9 +pop x10, x11 +pop x12, x13 +pop x14, x15 +pop x16, x17 +pop x18, x19 +pop x20, x21 +pop x22, x23 +pop x24, x25 +pop x26, x27 +pop x28, x29 +add sp, sp, #32 +.endm + +.macro invalid_exception, which + regsave_long + mov x1, #\which + mov x0, sp + bl arm64_invalid_exception + b . +.endm + +FUNCTION(arm64_exception_base) + +/* exceptions from current EL, using SP0 */ +LOCAL_FUNCTION(arm64_sync_exc_current_el_SP0) + invalid_exception 0 + +.org 0x080 +LOCAL_FUNCTION(arm64_irq_current_el_SP0) + invalid_exception 1 + +.org 0x100 +LOCAL_FUNCTION(arm64_fiq_current_el_SP0) + invalid_exception 2 + +.org 0x180 +LOCAL_FUNCTION(arm64_err_exc_current_el_SP0) + invalid_exception 3 + +/* exceptions from current EL, using SPx */ +.org 0x200 +LOCAL_FUNCTION(arm64_sync_exc_current_el_SPx) + regsave_long + mov x0, sp + bl arm64_sync_exception + b arm64_exc_shared_restore + +.org 0x280 +LOCAL_FUNCTION(arm64_irq_current_el_SPx) + regsave_long + mov x0, sp + bl platform_irq + b arm64_exc_shared_restore + +.org 0x300 +LOCAL_FUNCTION(arm64_fiq_current_el_SPx) + regsave_long + mov x0, sp + bl platform_fiq + b arm64_exc_shared_restore + +.org 0x380 +LOCAL_FUNCTION(arm64_err_exc_current_el_SPx) + invalid_exception 0x13 + +/* exceptions from lower EL, running arm64 */ +.org 0x400 +LOCAL_FUNCTION(arm64_sync_exc_lower_el_64) + invalid_exception 0x20 + +.org 0x480 +LOCAL_FUNCTION(arm64_irq_lower_el_64) + invalid_exception 0x21 + +.org 0x500 +LOCAL_FUNCTION(arm64_fiq_lower_el_64) + invalid_exception 0x22 + +.org 0x580 +LOCAL_FUNCTION(arm64_err_exc_lower_el_64) + invalid_exception 0x23 + +/* exceptions from lower EL, running arm32 */ +.org 0x600 +LOCAL_FUNCTION(arm64_sync_exc_lower_el_32) + invalid_exception 0x30 + +.org 0x680 +LOCAL_FUNCTION(arm64_irq_lower_el_32) + invalid_exception 0x31 + +.org 0x700 +LOCAL_FUNCTION(arm64_fiq_lower_el_32) + invalid_exception 0x32 + +.org 0x780 +LOCAL_FUNCTION(arm64_err_exc_lower_el_32) + invalid_exception 0x33 + +LOCAL_FUNCTION(arm64_exc_shared_restore) + regrestore_long + eret + diff --git a/arch/arm64/exceptions_c.c b/arch/arm64/exceptions_c.c new file mode 100644 index 00000000..a83ca7cb --- /dev/null +++ b/arch/arm64/exceptions_c.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014 Travis Geiselbrecht + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include +#include +#include + +#define SHUTDOWN_ON_FATAL 1 + +static void dump_iframe(const struct arm64_iframe_long *iframe) +{ + printf("iframe %p:\n", iframe); + printf("x0 0x%16llx x1 0x%16llx x2 0x%16llx x3 0x%16llx\n", iframe->r[0], iframe->r[1], iframe->r[2], iframe->r[3]); + printf("x4 0x%16llx x5 0x%16llx x6 0x%16llx x7 0x%16llx\n", iframe->r[4], iframe->r[5], iframe->r[6], iframe->r[7]); + printf("x8 0x%16llx x9 0x%16llx x10 0x%16llx x11 0x%16llx\n", iframe->r[8], iframe->r[9], iframe->r[10], iframe->r[11]); + printf("x12 0x%16llx x13 0x%16llx x14 0x%16llx x15 0x%16llx\n", iframe->r[12], iframe->r[13], iframe->r[14], iframe->r[15]); + printf("x16 0x%16llx x17 0x%16llx x18 0x%16llx x19 0x%16llx\n", iframe->r[16], iframe->r[17], iframe->r[18], iframe->r[19]); + printf("x20 0x%16llx x21 0x%16llx x22 0x%16llx x23 0x%16llx\n", iframe->r[20], iframe->r[21], iframe->r[22], iframe->r[23]); + printf("x24 0x%16llx x25 0x%16llx x26 0x%16llx x27 0x%16llx\n", iframe->r[24], iframe->r[25], iframe->r[26], iframe->r[27]); + printf("x28 0x%16llx x29 0x%16llx lr 0x%16llx sp 0x%16llx\n", iframe->r[28], iframe->r[29], iframe->r[30], iframe->r[31]); + printf("elr 0x%16llx\n", iframe->elr); + printf("spsr 0x%16llx\n", iframe->spsr); +} + +void arm64_sync_exception(struct arm64_iframe_long *iframe) +{ + printf("sync_exception\n"); + dump_iframe(iframe); + + uint32_t esr = ARM64_READ_SYSREG(esr_el1); + uint32_t ec = esr >> 26; + uint32_t il = (esr >> 25) & 0x1; + uint32_t iss = esr & ((1<<24) - 1); + + printf("ESR 0x%x: ec 0x%x, il 0x%x, iss 0x%x\n", esr, ec, il, iss); + + if (ec == 0x15) { // syscall + printf("syscall\n"); + return; + } + + panic("die\n"); +} + +void arm64_invalid_exception(struct arm64_iframe_long *iframe, unsigned int which) +{ + printf("invalid exception, which 0x%x\n", which); + dump_iframe(iframe); + + panic("die\n"); +} + + + diff --git a/arch/arm64/include/arch/arch_ops.h b/arch/arm64/include/arch/arch_ops.h new file mode 100644 index 00000000..c09ccf6f --- /dev/null +++ b/arch/arm64/include/arch/arch_ops.h @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2008-2014 Travis Geiselbrecht + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#pragma once + +#ifndef ASSEMBLY + +#include +#include +#include + +#define USE_GCC_ATOMICS 1 +#define ENABLE_CYCLE_COUNTER 1 + +// override of some routines +static inline void arch_enable_ints(void) +{ + CF; + __asm__ volatile("msr daifclr, #3" ::: "memory"); +} + +static inline void arch_disable_ints(void) +{ + __asm__ volatile("msr daifset, #3" ::: "memory"); + CF; +} + +// XXX +static inline bool arch_ints_disabled(void) +{ + unsigned int state; + + __asm__ volatile("mrs %0, cpsr" : "=r"(state)); + state &= (1<<7); + + return !!state; +} + +static inline int atomic_add(volatile int *ptr, int val) +{ +#if USE_GCC_ATOMICS + return __atomic_fetch_add(ptr, val, __ATOMIC_RELAXED); +#else + int old; + int temp; + int test; + + do { + __asm__ volatile( + "ldrex %[old], [%[ptr]]\n" + "adds %[temp], %[old], %[val]\n" + "strex %[test], %[temp], [%[ptr]]\n" + : [old]"=&r" (old), [temp]"=&r" (temp), [test]"=&r" (test) + : [ptr]"r" (ptr), [val]"r" (val) + : "memory", "cc"); + + } while (test != 0); + + return old; +#endif +} + +static inline int atomic_or(volatile int *ptr, int val) +{ +#if USE_GCC_ATOMICS + return __atomic_fetch_or(ptr, val, __ATOMIC_RELAXED); +#else + int old; + int temp; + int test; + + do { + __asm__ volatile( + "ldrex %[old], [%[ptr]]\n" + "orrs %[temp], %[old], %[val]\n" + "strex %[test], %[temp], [%[ptr]]\n" + : [old]"=&r" (old), [temp]"=&r" (temp), [test]"=&r" (test) + : [ptr]"r" (ptr), [val]"r" (val) + : "memory", "cc"); + + } while (test != 0); + + return old; +#endif +} + +static inline int atomic_and(volatile int *ptr, int val) +{ +#if USE_GCC_ATOMICS + return __atomic_fetch_and(ptr, val, __ATOMIC_RELAXED); +#else + int old; + int temp; + int test; + + do { + __asm__ volatile( + "ldrex %[old], [%[ptr]]\n" + "ands %[temp], %[old], %[val]\n" + "strex %[test], %[temp], [%[ptr]]\n" + : [old]"=&r" (old), [temp]"=&r" (temp), [test]"=&r" (test) + : [ptr]"r" (ptr), [val]"r" (val) + : "memory", "cc"); + + } while (test != 0); + + return old; +#endif +} + +static inline int atomic_swap(volatile int *ptr, int val) +{ +#if USE_GCC_ATOMICS + return __atomic_exchange_n(ptr, val, __ATOMIC_RELAXED); +#else + int old; + int test; + + do { + __asm__ volatile( + "ldrex %[old], [%[ptr]]\n" + "strex %[test], %[val], [%[ptr]]\n" + : [old]"=&r" (old), [test]"=&r" (test) + : [ptr]"r" (ptr), [val]"r" (val) + : "memory"); + + } while (test != 0); + + return old; +#endif +} + +static inline int atomic_cmpxchg(volatile int *ptr, int oldval, int newval) +{ + int old; + int test; + + do { + __asm__ volatile( + "ldrex %[old], [%[ptr]]\n" + "mov %[test], #0\n" + "teq %[old], %[oldval]\n" +#if ARM_ISA_ARMV7M + "bne 0f\n" + "strex %[test], %[newval], [%[ptr]]\n" + "0:\n" +#else + "strexeq %[test], %[newval], [%[ptr]]\n" +#endif + : [old]"=&r" (old), [test]"=&r" (test) + : [ptr]"r" (ptr), [oldval]"Ir" (oldval), [newval]"r" (newval) + : "cc"); + + } while (test != 0); + + return old; +} + +static inline uint32_t arch_cycle_count(void) +{ +#if ARM_ISA_ARM7M +#if ENABLE_CYCLE_COUNTER +#define DWT_CYCCNT (0xE0001004) + return *REG32(DWT_CYCCNT); +#else + return 0; +#endif +#elif ARM_ISA_ARMV7 + uint32_t count; + __asm__ volatile("mrc p15, 0, %0, c9, c13, 0" + : "=r" (count) + ); + return count; +#else +//#warning no arch_cycle_count implementation + return 0; +#endif +} + +#endif // ASSEMBLY + diff --git a/arch/arm64/include/arch/arch_thread.h b/arch/arm64/include/arch/arch_thread.h new file mode 100644 index 00000000..06494481 --- /dev/null +++ b/arch/arm64/include/arch/arch_thread.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2014 Travis Geiselbrecht + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#pragma once + +#include + +struct arch_thread { + vaddr_t sp; +}; + diff --git a/arch/arm64/include/arch/arm64.h b/arch/arm64/include/arch/arm64.h new file mode 100644 index 00000000..1a3519ea --- /dev/null +++ b/arch/arm64/include/arch/arm64.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014 Travis Geiselbrecht + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#pragma once + +#include +#include +#include + +__BEGIN_CDECLS + +#define DSB __asm__ volatile("dsb" ::: "memory") +#define ISB __asm__ volatile("isb" ::: "memory") + +#define ARM64_READ_SYSREG(reg) \ +({ \ + uint64_t _val; \ + __asm__ volatile("mrs %0," #reg : "=r" (_val)); \ + _val; \ +}) + +#define ARM64_WRITE_SYSREG(reg, val) \ +({ \ + __asm__ volatile("msr " #reg ", %0" :: "r" (val)); \ + ISB; \ +}) + +void arm64_context_switch(vaddr_t *old_sp, vaddr_t new_sp); + +/* exception handling */ +struct arm64_iframe_long { + uint64_t r[32]; + uint64_t elr; + uint64_t spsr; +}; + +extern void arm64_exception_base(void); +void arm64_el3_to_el1(void); + +__END_CDECLS + diff --git a/arch/arm64/include/arch/defines.h b/arch/arm64/include/arch/defines.h new file mode 100644 index 00000000..34eb68c3 --- /dev/null +++ b/arch/arm64/include/arch/defines.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2008 Travis Geiselbrecht + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#pragma once + +/* arm specific stuff */ +#define PAGE_SIZE 4096 + +#define CACHE_LINE 32 + diff --git a/arch/arm64/rules.mk b/arch/arm64/rules.mk new file mode 100644 index 00000000..36d8b258 --- /dev/null +++ b/arch/arm64/rules.mk @@ -0,0 +1,68 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +MODULE := $(LOCAL_DIR) + +GLOBAL_DEFINES += \ + ARM64_CPU_$(ARM_CPU)=1 \ + ARM_ISA_ARMV8=1 + +GLOBAL_INCLUDES += \ + $(LOCAL_DIR)/include + +MODULE_SRCS += \ + $(LOCAL_DIR)/arch.c \ + $(LOCAL_DIR)/asm.S \ + $(LOCAL_DIR)/exceptions.S \ + $(LOCAL_DIR)/exceptions_c.c \ + $(LOCAL_DIR)/thread.c \ + $(LOCAL_DIR)/start.S \ + +# $(LOCAL_DIR)/arm/start.S \ + $(LOCAL_DIR)/arm/cache-ops.S \ + $(LOCAL_DIR)/arm/cache.c \ + $(LOCAL_DIR)/arm/ops.S \ + $(LOCAL_DIR)/arm/faults.c \ + $(LOCAL_DIR)/arm/mmu.c \ + $(LOCAL_DIR)/arm/dcc.S + +GLOBAL_DEFINES += \ + ARCH_DEFAULT_STACK_SIZE=8192 + +# try to find the toolchain +ifndef TOOLCHAIN_PREFIX +TOOLCHAIN_PREFIX := aarch64-elf- +endif + +FOUNDTOOL=$(shell which $(TOOLCHAIN_PREFIX)gcc) +ifeq ($(FOUNDTOOL),) +$(error cannot find toolchain, please set TOOLCHAIN_PREFIX or add it to your path) +endif +$(info TOOLCHAIN_PREFIX = $(TOOLCHAIN_PREFIX)) + +# make sure some bits were set up +MEMVARS_SET := 0 +ifneq ($(MEMBASE),) +MEMVARS_SET := 1 +endif +ifneq ($(MEMSIZE),) +MEMVARS_SET := 1 +endif +ifeq ($(MEMVARS_SET),0) +$(error missing MEMBASE or MEMSIZE variable, please set in target rules.mk) +endif + +LIBGCC := $(shell $(TOOLCHAIN_PREFIX)gcc $(GLOBAL_COMPILEFLAGS) $(THUMBCFLAGS) -print-libgcc-file-name) +$(info LIBGCC = $(LIBGCC)) +$(info GLOBAL_COMPILEFLAGS = $(GLOBAL_COMPILEFLAGS) $(THUMBCFLAGS)) + +# potentially generated files that should be cleaned out with clean make rule +GENERATED += \ + $(BUILDDIR)/system-onesegment.ld + +# rules for generating the linker script +$(BUILDDIR)/system-onesegment.ld: $(LOCAL_DIR)/system-onesegment.ld $(wildcard arch/*.ld) + @echo generating $@ + @$(MKDIR) + $(NOECHO)sed "s/%MEMBASE%/$(MEMBASE)/;s/%MEMSIZE%/$(MEMSIZE)/" < $< > $@ + +include make/module.mk diff --git a/arch/arm64/start.S b/arch/arm64/start.S new file mode 100644 index 00000000..389b05dd --- /dev/null +++ b/arch/arm64/start.S @@ -0,0 +1,16 @@ +#include + +.section .text.boot +FUNCTION(_start) + ldr x0, =__stack_end + mov sp, x0 + + bl lk_main + b . + +.section .bss.prebss.stack + .align 4 +DATA(__stack) + .skip 0x2000 +DATA(__stack_end) + diff --git a/arch/arm64/system-onesegment.ld b/arch/arm64/system-onesegment.ld new file mode 100644 index 00000000..f37a5cb8 --- /dev/null +++ b/arch/arm64/system-onesegment.ld @@ -0,0 +1,101 @@ +OUTPUT_FORMAT("elf64-littleaarch64", "elf64-bigaarch64", "elf64-littleaarch64") +OUTPUT_ARCH(aarch64) + +ENTRY(_start) +SECTIONS +{ + . = %MEMBASE%; + + /* text/read-only data */ + .text : { + KEEP(*(.text.boot.vectab)) + KEEP(*(.text.boot)) + *(.text* .sram.text.glue_7* .gnu.linkonce.t.*) + } + + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) } + .rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) } + .rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) } + .rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) } + .rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) } + .rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } =0x9090 + .plt : { *(.plt) } + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + __exidx_start = .; + .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } + __exidx_end = .; + + .rodata : ALIGN(8) { + __rodata_start = .; + *(.rodata .rodata.* .gnu.linkonce.r.*) +INCLUDE "arch/shared_rodata_sections.ld" + . = ALIGN(8); + __rodata_end = .; + } + + + .data : ALIGN(8) { + /* writable data */ + __data_start_rom = .; + /* in one segment binaries, the rom data address is on top of the ram data address */ + __data_start = .; + *(.data .data.* .gnu.linkonce.d.*) +INCLUDE "arch/shared_data_sections.ld" + } + + .ctors : ALIGN(8) { + __ctor_list = .; + KEEP(*(.ctors .init_array)) + __ctor_end = .; + } + .dtors : ALIGN(8) { + __dtor_list = .; + KEEP(*(.dtors .fini_array)) + __dtor_end = .; + } + .got : { *(.got.plt) *(.got) } + .dynamic : { *(.dynamic) } + + __data_end = .; + + /* unintialized data (in same segment as writable data) */ + .bss : ALIGN(8) { + KEEP(*(.bss.prebss.*)) + . = ALIGN(8); + __bss_start = .; + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(8); + __bss_end = .; + } + + . = ALIGN(8); + _end = .; + + . = %MEMBASE% + %MEMSIZE%; + _end_of_ram = .; + + /* Strip unnecessary stuff */ + /DISCARD/ : { *(.comment .note .eh_frame) } +} diff --git a/arch/arm64/thread.c b/arch/arm64/thread.c new file mode 100644 index 00000000..db0cae59 --- /dev/null +++ b/arch/arm64/thread.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2008 Travis Geiselbrecht + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include +#include +#include +#include +#include +#include +#include + +#define LOCAL_TRACE 0 + +struct context_switch_frame { + vaddr_t lr; + vaddr_t r18; + vaddr_t r19; + vaddr_t r20; + vaddr_t r21; + vaddr_t r22; + vaddr_t r23; + vaddr_t r24; + vaddr_t r25; + vaddr_t r26; + vaddr_t r27; + vaddr_t r28; + vaddr_t r29; +}; + +extern void arm64_context_switch(addr_t *old_sp, addr_t new_sp); + +static void initial_thread_func(void) __NO_RETURN; +static void initial_thread_func(void) +{ + int ret; + + LTRACEF("initial_thread_func: thread %p calling %p with arg %p\n", current_thread, current_thread->entry, current_thread->arg); + + /* exit the implicit critical section we're within */ + exit_critical_section(); + + ret = current_thread->entry(current_thread->arg); + + LTRACEF("initial_thread_func: thread %p exiting with %d\n", current_thread, ret); + + thread_exit(ret); +} + +void arch_thread_initialize(thread_t *t) +{ + // create a default stack frame on the stack + vaddr_t stack_top = (vaddr_t)t->stack + t->stack_size; + + // make sure the top of the stack is 16 byte aligned for EABI compliance + stack_top = ROUNDDOWN(stack_top, 16); + + struct context_switch_frame *frame = (struct context_switch_frame *)(stack_top); + frame--; + + // fill it in + memset(frame, 0, sizeof(*frame)); + frame->lr = (vaddr_t)&initial_thread_func; + + // set the stack pointer + t->arch.sp = (vaddr_t)frame; +} + +void arch_context_switch(thread_t *oldthread, thread_t *newthread) +{ + LTRACEF("old %p (%s), new %p (%s)\n", oldthread, oldthread->name, newthread, newthread->name); + arm64_context_switch(&oldthread->arch.sp, newthread->arch.sp); +} + diff --git a/lib/libc/string/arch/arm64/rules.mk b/lib/libc/string/arch/arm64/rules.mk new file mode 100644 index 00000000..7a97451a --- /dev/null +++ b/lib/libc/string/arch/arm64/rules.mk @@ -0,0 +1,2 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) +