From 8f363e5d7123feec49f7a8bad98fdf99b9e3bc0e Mon Sep 17 00:00:00 2001 From: Claudio Fontana <claudio.fontana@huawei.com> Date: Thu, 20 Mar 2014 17:06:50 +0100 Subject: [PATCH] arch/aarch64: first implementation Signed-off-by: Claudio Fontana <claudio.fontana@huawei.com> --- arch/aarch64/arch-cpu.cc | 18 ++++ arch/aarch64/arch-cpu.hh | 50 +++++++++++ arch/aarch64/arch-setup.cc | 47 +++++++++++ arch/aarch64/arch-setup.hh | 20 +++++ arch/aarch64/arch-switch.hh | 74 +++++++++++++++++ arch/aarch64/arch-thread-state.hh | 17 ++++ arch/aarch64/arch.hh | 104 +++++++++++++++++++++++ arch/aarch64/arm-clock.cc | 45 ++++++++++ arch/aarch64/arm-clock.hh | 15 ++++ arch/aarch64/backtrace.cc | 33 ++++++++ arch/aarch64/bitops.h | 31 +++++++ arch/aarch64/boot.S | 75 +++++++++++++++++ arch/aarch64/elf-dl.S | 32 +++++++ arch/aarch64/entry.S | 69 ++++++++++++++++ arch/aarch64/exceptions.hh | 60 ++++++++++++++ arch/aarch64/loader.ld | 133 ++++++++++++++++++++++++++++++ arch/aarch64/macros.S | 14 ++++ arch/aarch64/math.cc | 16 ++++ arch/aarch64/preboot.S | 19 +++++ arch/aarch64/preboot.ld | 4 + arch/aarch64/processor.hh | 117 ++++++++++++++++++++++++++ arch/aarch64/safe-ptr.hh | 31 +++++++ arch/aarch64/signal.cc | 54 ++++++++++++ arch/aarch64/smp.cc | 29 +++++++ arch/aarch64/smp.hh | 15 ++++ arch/aarch64/string.cc | 35 ++++++++ 26 files changed, 1157 insertions(+) create mode 100644 arch/aarch64/arch-cpu.cc create mode 100644 arch/aarch64/arch-cpu.hh create mode 100644 arch/aarch64/arch-setup.cc create mode 100644 arch/aarch64/arch-setup.hh create mode 100644 arch/aarch64/arch-switch.hh create mode 100644 arch/aarch64/arch-thread-state.hh create mode 100644 arch/aarch64/arch.hh create mode 100644 arch/aarch64/arm-clock.cc create mode 100644 arch/aarch64/arm-clock.hh create mode 100644 arch/aarch64/backtrace.cc create mode 100644 arch/aarch64/bitops.h create mode 100644 arch/aarch64/boot.S create mode 100644 arch/aarch64/elf-dl.S create mode 100644 arch/aarch64/entry.S create mode 100644 arch/aarch64/exceptions.hh create mode 100644 arch/aarch64/loader.ld create mode 100644 arch/aarch64/macros.S create mode 100644 arch/aarch64/math.cc create mode 100644 arch/aarch64/preboot.S create mode 100644 arch/aarch64/preboot.ld create mode 100644 arch/aarch64/processor.hh create mode 100644 arch/aarch64/safe-ptr.hh create mode 100644 arch/aarch64/signal.cc create mode 100644 arch/aarch64/smp.cc create mode 100644 arch/aarch64/smp.hh create mode 100644 arch/aarch64/string.cc diff --git a/arch/aarch64/arch-cpu.cc b/arch/aarch64/arch-cpu.cc new file mode 100644 index 000000000..e76eea954 --- /dev/null +++ b/arch/aarch64/arch-cpu.cc @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2013 Cloudius Systems, Ltd. + * + * 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. + */ + +#include "arch-cpu.hh" +#include <osv/sched.hh> +#include <osv/debug.hh> + +namespace sched { + +__thread unsigned exception_depth = 0; + +} diff --git a/arch/aarch64/arch-cpu.hh b/arch/aarch64/arch-cpu.hh new file mode 100644 index 000000000..7b631e06b --- /dev/null +++ b/arch/aarch64/arch-cpu.hh @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2013 Cloudius Systems, Ltd. + * + * 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 ARCH_CPU_HH +#define ARCH_CPU_HH + +#include "processor.hh" +#include "osv/pagealloc.hh" +#include <osv/debug.h> + +namespace sched { + +struct arch_cpu; +struct arch_thread; + +struct arch_cpu { + arch_cpu(); + + unsigned int gic_id; + + void init_on_cpu(); +}; + +struct arch_thread { +}; + +struct arch_fpu { + struct processor::fpu_state s; + void save() { processor::fpu_state_save(&s); } + void restore() { processor::fpu_state_load(&s); } +}; + +inline arch_cpu::arch_cpu() +{ +} + +inline void arch_cpu::init_on_cpu() +{ + processor::halt_no_interrupts(); +} + +} + +#endif /* ARCH_CPU_HH */ diff --git a/arch/aarch64/arch-setup.cc b/arch/aarch64/arch-setup.cc new file mode 100644 index 000000000..d72d42187 --- /dev/null +++ b/arch/aarch64/arch-setup.cc @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2013 Cloudius Systems, Ltd. + * + * 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. + */ + +#include "arch.hh" +#include "arch-setup.hh" +#include <osv/sched.hh> +#include <osv/mempool.hh> +#include <osv/elf.hh> +#include <osv/types.h> +#include <string.h> +#include <osv/boot.hh> +#include <osv/debug.hh> + +extern elf::Elf64_Ehdr* elf_header; +extern size_t elf_size; +extern void* elf_start; +extern boot_time_chart boot_time; + +void arch_setup_free_memory() +{ + register u64 edata; + asm ("adrp %0, .edata" : "=r"(edata)); + + elf_start = reinterpret_cast<void*>(elf_header); + elf_size = (u64)edata - (u64)elf_start; + + /* just a test for now, we hardcode 512MB of memory */ + u64 addr = (u64)elf_start + elf_size + 0x10000; + addr = addr & ~0xffffull; + + memory::free_initial_memory_range((void*)addr, 0x20000000); +} + +void arch_setup_tls(thread_control_block *tcb) +{ + asm volatile ("msr tpidr_el0, %0; isb; " :: "r"(tcb)); +} + +void arch_init_premain() +{ +} diff --git a/arch/aarch64/arch-setup.hh b/arch/aarch64/arch-setup.hh new file mode 100644 index 000000000..9aa3d06f8 --- /dev/null +++ b/arch/aarch64/arch-setup.hh @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2013 Cloudius Systems, Ltd. + * + * 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 ARCH_SETUP_HH_ +#define ARCH_SETUP_HH_ + +#include <osv/tls.hh> + +void arch_init_premain(); +void arch_setup_tls(thread_control_block *tcb); + +void arch_setup_free_memory(); + +#endif /* ARCH_SETUP_HH_ */ diff --git a/arch/aarch64/arch-switch.hh b/arch/aarch64/arch-switch.hh new file mode 100644 index 000000000..763534f83 --- /dev/null +++ b/arch/aarch64/arch-switch.hh @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2013 Cloudius Systems, Ltd. + * + * 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 ARCH_SWITCH_HH_ +#define ARCH_SWITCH_HH_ + +#include <osv/barrier.hh> +#include <string.h> + +extern "C" { +void thread_main(void); +void thread_main_c(sched::thread* t); +void stack_trampoline(sched::thread* t, void (*func)(sched::thread*), + void** stacktop); +} + +namespace sched { + +void thread::switch_to() +{ + abort(); +} + +void thread::switch_to_first() +{ + abort(); +} + +void thread::init_stack() +{ + auto& stack = _attr._stack; + if (!stack.size) { + stack.size = 65536; + } + if (!stack.begin) { + stack.begin = malloc(stack.size); + stack.deleter = stack.default_deleter; + } + void** stacktop = reinterpret_cast<void**>(stack.begin + stack.size); + _state.fp = this; + _state.pc = reinterpret_cast<void*>(thread_main); + _state.sp = stacktop; +} + +void thread::setup_tcb() +{ + assert(tls.size); + + void* p = malloc(sched::tls.size + sizeof(*_tcb)); + memcpy(p, sched::tls.start, sched::tls.size); + _tcb = static_cast<thread_control_block*>(p + tls.size); + _tcb->self = _tcb; + _tcb->tls_base = p; +} + +void thread::free_tcb() +{ + free(_tcb->tls_base); +} + +void thread_main_c(thread* t) +{ + abort(); +} + +} + +#endif /* ARCH_SWITCH_HH_ */ diff --git a/arch/aarch64/arch-thread-state.hh b/arch/aarch64/arch-thread-state.hh new file mode 100644 index 000000000..bc592b6fb --- /dev/null +++ b/arch/aarch64/arch-thread-state.hh @@ -0,0 +1,17 @@ +/* + * 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 ARCH_THREAD_STATE_HH_ +#define ARCH_THREAD_STATE_HH_ + +struct thread_state { + void* sp; + void* fp; + void* pc; +}; + +#endif /* ARCH_THREAD_STATE_HH_ */ diff --git a/arch/aarch64/arch.hh b/arch/aarch64/arch.hh new file mode 100644 index 000000000..6f64c9ed9 --- /dev/null +++ b/arch/aarch64/arch.hh @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2013 Cloudius Systems, Ltd. + * + * 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 ARCH_HH_ +#define ARCH_HH_ + +#include "processor.hh" + +// architecture independent interface for architecture dependent operations + +namespace arch { + +#define CACHELINE_ALIGNED __attribute__((aligned(64))) + +inline void irq_disable() +{ + processor::irq_disable(); +} + +__attribute__((no_instrument_function)) +inline void irq_disable_notrace(); + +inline void irq_disable_notrace() +{ + processor::irq_disable_notrace(); +} + +inline void irq_enable() +{ + processor::irq_enable(); +} + +inline void wait_for_interrupt() +{ + processor::wait_for_interrupt(); +} + +inline void halt_no_interrupts() +{ + processor::halt_no_interrupts(); +} + +class irq_flag { +public: + void save() { + asm volatile("mrs %0, daif;" : "=r"(daif) :: "memory"); + } + + void restore() { + asm volatile("msr daif, %0" :: "r"(daif) : "memory"); + } + bool enabled() const { + return !(daif & processor::daif_i); + } + +private: + unsigned long daif; +}; + +class irq_flag_notrace { +public: + __attribute__((no_instrument_function)) void save(); + __attribute__((no_instrument_function)) void restore(); + __attribute__((no_instrument_function)) bool enabled() const; +private: + unsigned long daif; +}; + +inline void irq_flag_notrace::save() { + asm volatile("mrs %0, daif;" : "=r"(daif) :: "memory"); +} + +inline void irq_flag_notrace::restore() { + asm volatile("msr daif, x0" :: "r"(daif) : "memory"); +} + +inline bool irq_flag_notrace::enabled() const { + return !(daif & processor::daif_i); +} + +inline bool irq_enabled() +{ + irq_flag f; + f.save(); + return f.enabled(); +} + +extern bool tls_available() __attribute__((no_instrument_function)); + +inline bool tls_available() +{ + /* XXX */ + return false; +} + +} // namespace arch + +#endif /* ARCH_HH_ */ diff --git a/arch/aarch64/arm-clock.cc b/arch/aarch64/arm-clock.cc new file mode 100644 index 000000000..f0ac5fe92 --- /dev/null +++ b/arch/aarch64/arm-clock.cc @@ -0,0 +1,45 @@ +/* + * 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. + */ + +#include "drivers/clockevent.hh" +#include "drivers/clock.hh" +#include "arm-clock.hh" + +using namespace processor; + +class arm_clock_events : public clock_event_driver { +public: + explicit arm_clock_events(); + ~arm_clock_events(); + virtual void setup_on_cpu(); + virtual void set(std::chrono::nanoseconds nanos); +private: + unsigned _vector; +}; + + +arm_clock_events::arm_clock_events() +{ +} + +arm_clock_events::~arm_clock_events() +{ +} + +void arm_clock_events::setup_on_cpu() +{ +} + +void arm_clock_events::set(std::chrono::nanoseconds nanos) +{ +} + +void __attribute__((constructor)) init_arm_clock() +{ + debug_early_entry("init_arm_clock()"); + clock_event = new arm_clock_events; +} diff --git a/arch/aarch64/arm-clock.hh b/arch/aarch64/arm-clock.hh new file mode 100644 index 000000000..60cc5d0a0 --- /dev/null +++ b/arch/aarch64/arm-clock.hh @@ -0,0 +1,15 @@ +/* + * 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 ARCH_ARM_CLOCK_HH +#define ARCH_ARM_CLOCK_HH + +namespace processor { +} + + +#endif /* ARCH_ARM_CLOCK_HH */ diff --git a/arch/aarch64/backtrace.cc b/arch/aarch64/backtrace.cc new file mode 100644 index 000000000..4f369db06 --- /dev/null +++ b/arch/aarch64/backtrace.cc @@ -0,0 +1,33 @@ +/* + * 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. + */ + +#include "safe-ptr.hh" +#include <osv/debug.h> + +struct frame { + frame* next; + void* pc; +}; + +int backtrace_safe(void** pc, int nr) +{ + register frame* fp; + frame* next; + + asm("mov %0, x29" : "=r"(fp)); + + int i = 0; + while (i < nr + && safe_load(&fp->next, next) + && safe_load(&fp->pc, pc[i]) + && pc[i]) { + fp = next; + ++i; + } + + return i; +} diff --git a/arch/aarch64/bitops.h b/arch/aarch64/bitops.h new file mode 100644 index 000000000..0e041971b --- /dev/null +++ b/arch/aarch64/bitops.h @@ -0,0 +1,31 @@ +/* + * 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 ARCH_BITOPS_H_ +#define ARCH_BITOPS_H_ +static inline unsigned int +bsrl(unsigned int mask) +{ + unsigned int result; + asm volatile("clz %1,%0" : "=r" (result) : "r" (mask)); + return result; +} + +static inline unsigned long +bsrq(unsigned long mask) +{ + unsigned long result; + asm volatile("clz %1,%0" : "=r" (result) : "r" (mask)); + return result; +} + +static inline int +fls(int mask) +{ + return (mask == 0 ? mask : (int)bsrl((unsigned int)mask) + 1); +} +#endif /* ARCH_BITOPS_H */ diff --git a/arch/aarch64/boot.S b/arch/aarch64/boot.S new file mode 100644 index 000000000..e46518d83 --- /dev/null +++ b/arch/aarch64/boot.S @@ -0,0 +1,75 @@ +/* + * 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. + */ + +.text +.align 16 +.globl start_elf +start_elf: + /* elf program start address */ + /* input: x0 = elf header address */ + mov x2, x0 // elf_header ptr => x2 + bl validate_el // check that we are at EL1 or die + + bl init_stack + bl zero_bss // initialize bss contents to 0 + bl init_boot_cpu + + adrp x1, elf_header // requires page alignment */ + str x2, [x1] // store elf header address + + mov x29, xzr + mov x30, xzr + bl premain + /* + adrp x2, __argc + ldr x0, [x2] + adrp x2, __argv + ldr x1, [x2] + b main + */ + +init_stack: + adrp x0, init_stack_top + mov sp, x0 + ret + +validate_el: + mrs x0, currentel + ubfm x0, x0, #2, #3 // current EL[3:2] -> X0 + cmp x0, #1 + b.ne halt + ret + +halt: wfi + b halt + +zero_bss: + adrp x0, .bss + adrp x1, .edata +zero_bss_loop: + stp xzr, xzr, [x0], #16 + cmp x0, x1 + b.lo zero_bss_loop + ret +init_boot_cpu: + mov x0, #3 << 20 + msr cpacr_el1, x0 // no trapping on FP/SIMD instructions + msr mdscr_el1, xzr // monitor debug: all disabled + isb + ret + +.bss +.align 16 +init_stack_bottom = . +. = . + 4096*4 +init_stack_top = . + +/* hmm should we provide an interrupt stack? +. = . + 4096*10 +.global interrupt_stack_top +interrupt_stack_top = . +*/ diff --git a/arch/aarch64/elf-dl.S b/arch/aarch64/elf-dl.S new file mode 100644 index 000000000..ab38c624c --- /dev/null +++ b/arch/aarch64/elf-dl.S @@ -0,0 +1,32 @@ +/* + * 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. + */ + +#include "macros.S" + +/* XXX this will halt, because it is not reached/tested. + When we reach this, test, verify, develop against the ELF AArch64 ABI */ +.text + +.global __elf_resolve_pltgot + +// calling convention: +// sp + 8: index +// sp + 0: object +__elf_resolve_pltgot: + .type __elf_resolve_pltgot, @function + +1: wfi + b 1b + sub sp, sp, #16 // make room for resolved address + + /* XXX + * push caller-saved gp/fp-regs, + * elf_resolve_pltgot passing x0 and x1 with the args, + * restore caller-saved gp/fp-regs. */ + + add sp, sp, #16 + ret diff --git a/arch/aarch64/entry.S b/arch/aarch64/entry.S new file mode 100644 index 000000000..20a312490 --- /dev/null +++ b/arch/aarch64/entry.S @@ -0,0 +1,69 @@ +/* + * 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. + */ + +/* XXX TODO nothing to see here, move along XXX */ + +#include "macros.S" + /* + .macro exception_entry name, handler, has_error_code + push_pair x28, x29 + push_pair x26, x27 + push_pair x24, x25 + push_pair x22, x23 + push_pair x20, x21 + + push_pair x18, x19 + push_pair x16, x17 + push_pair x14, x15 + push_pair x12, x13 + push_pair x10, x11 + + push_pair x8, x9 + push_pair x6, x7 + push_pair x4, x5 + push_pair x2, x3 + push_pair x0, x1 + + push_pair x29, x30 + ... + .endm + +.macro exception_error_entry name, handler + exception_entry \name, \handler, 1 +.endm + +.macro exception_noerror_entry name, handler + exception_entry \name, \handler, 0 +.endm + +.cfi_sections .eh_frame, .debug_frame + +.text + +*/ + +.global thread_main +thread_main: + .type thread_main, @function + mov x0, x29 + bl thread_main_c + +.global call_signal_handler_thunk +call_signal_handler_thunk: + .type call_signal_handler_thunk, @function + # stack contains a signal_frame + /* + .cfi_offset reg, offset + ... + mov x0, sp + call call_signal_handler + # FIXME: fpu + + pop_pair... + add sp, sp, 16 # error_code + */ + ret diff --git a/arch/aarch64/exceptions.hh b/arch/aarch64/exceptions.hh new file mode 100644 index 000000000..25f45bb1c --- /dev/null +++ b/arch/aarch64/exceptions.hh @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2013 Cloudius Systems, Ltd. + * + * 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 EXCEPTIONS_HH +#define EXCEPTIONS_HH + +#include <stdint.h> +#include <functional> +#include <osv/types.h> +#include <osv/rcu.hh> +#include <osv/mutex.h> +#include <vector> + +struct exception_frame { + u64 regs[31]; + u64 sp; + u64 pc; + u64 pstate; + u64 error_code; + u64 reserved; /* align to 16 */ +}; + +extern __thread exception_frame* current_interrupt_frame; + +struct shared_vector { + unsigned vector; + unsigned id; + shared_vector(unsigned v, unsigned i) + : vector(v), id(i) + {}; +}; + +class interrupt_table { +public: + interrupt_table(); + void load_on_cpu(); + unsigned register_handler(std::function<void ()> handler); + // The pre_eoi should 'true' when the interrupt is for the device, 'false' otherwise. + shared_vector register_level_triggered_handler(unsigned gsi, std::function<bool ()> pre_eoi, std::function<void ()> handler); + void unregister_level_triggered_handler(shared_vector v); + unsigned register_interrupt_handler(std::function<bool ()> pre_eoi, std::function<void ()> eoi, std::function<void ()> handler); + void unregister_handler(unsigned vector); + void invoke_interrupt(unsigned vector); +}; + +extern interrupt_table interrupt_table; + +extern "C" { + void page_fault(exception_frame* ef); +} + +bool fixup_fault(exception_frame*); + +#endif /* EXCEPTIONS_HH */ diff --git a/arch/aarch64/loader.ld b/arch/aarch64/loader.ld new file mode 100644 index 000000000..a027cbcdb --- /dev/null +++ b/arch/aarch64/loader.ld @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2013 Cloudius Systems, Ltd. + * + * 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. + */ + +SECTIONS +{ + /* Set the initial program counter to one page beyond the minimal + * aligned segment size. This allows the ELF header to reside with + * the text segment, which is useful since we need the ELF header + * to link against libraries later on. + * + * We can't export the ELF header base as a symbol, because ld + * insists on moving stuff around if we do. + */ + . = 0x40091000; + + .dynamic : ALIGN(16) { *(.dynamic) } : dynamic : text + + .rela.dyn : ALIGN(4096) { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + *(.rela.ifunc) + } : dynamic : text + + .rela.plt : ALIGN(4096) { + *(.rela.plt) + __rela_iplt_start = .; + *(.rela.iplt) + __rela_iplt_end = .; + } : dynamic : text + + .plt : ALIGN (4096) { *(.plt) *(.iplt) } : dynamic : text + .got : ALIGN (4096) { *(.got) *(.igot) } : dynamic : text + .got.plt : ALIGN (4096) { *(.got.plt) *(.igot.plt) } : dynamic : text + + .text : ALIGN (16) { + text_start = .; + *(.text.unlikely .text.*_unlikely .text.unlikely.*) + *(.text.exit .text.exit.*) + *(.text.startup .text.startup.*) + *(.text.hot .text.hot.*) + *(.text .stub .text.* .gnu.linkonce.t.*) + text_end = .; + } : text + + .eh_frame : { *(.eh_frame) } : text + .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame + .rodata : { *(.rodata*) } :text + .note : { *(.note*) } :text :note + + .gcc_except_table : { *(.gcc_except_table) *(.gcc_except_table.*) } : text + + .tracepoint_patch_sites : ALIGN(8) { + __tracepoint_patch_sites_start = .; + *(.tracepoint_patch_sites) + __tracepoint_patch_sites_end = .; + } : text + + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) } : text + + .data : { *(.data .data.*) } : text + + _init_array_start = .; + .init_array : ALIGN(16) { + *(SORT_BY_NAME(.preinit_array.*) .preinit_array) + *(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)) + *(.init_array .ctors) + } : text + _init_array_end = .; + + .percpu : ALIGN (4096) { + _percpu_start = .; + *(.percpu) + . = ALIGN(4096); + _percpu_end = .; + } + .percpu_workers : ALIGN (4096) { + _percpu_workers_start = .; + *(.percpu_workers) + _percpu_workers_end = .; + } + + .tdata : ALIGN(64) { *(.tdata .tdata.* .gnu.linkonce.td.*) } : tls : text + .tbss : ALIGN(64) { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } : tls : text + .tls_template_size = SIZEOF(.tdata) + SIZEOF(.tbss); + .bss : { *(.dynbss .bss .bss.* .gnu.linkonce.b.*) } : text + + . = ALIGN(64); + tcb0 = .; + . = . + .tls_template_size + 256; + . = ALIGN(4096); + .edata = .; + + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_frame 0 : { *(.debug_frame) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_aranges 0 : { *(.debug_aranges) } + .debug_ranges 0 : { *(.debug_ranges) } + .debug_line 0 : { *(.debug_line) } + .debug_loc 0 : { *(.debug_loc) } + .debug_str 0 : { *(.debug_str) } + .debug_macinfo 0 : { *(.debug_macinfo) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + .debug_weaknames 0 : { *(.debug_weaknames) } + .gdb_index 0 : { *(.gdb_index) } + .comment : { *(.comment) } +} +PHDRS { + text PT_LOAD FILEHDR PHDRS; + tls PT_TLS; + dynamic PT_DYNAMIC; + eh_frame PT_GNU_EH_FRAME; + note PT_NOTE; +} +ENTRY(start_elf); diff --git a/arch/aarch64/macros.S b/arch/aarch64/macros.S new file mode 100644 index 000000000..8c790ca27 --- /dev/null +++ b/arch/aarch64/macros.S @@ -0,0 +1,14 @@ +/* + * 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. + */ + +.macro push_pair reg1, reg2 + stp \reg1, \reg2, [sp, #-16]! +.endm + +.macro pop_pair reg1, reg2 + ldp \reg1, \reg2, [sp], #16 +.endm diff --git a/arch/aarch64/math.cc b/arch/aarch64/math.cc new file mode 100644 index 000000000..908da3492 --- /dev/null +++ b/arch/aarch64/math.cc @@ -0,0 +1,16 @@ +/* + * 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. + */ + +/* XXX todo XXX */ +#include <math.h> +#include <osv/types.h> + +extern "C" +int __isnan(double v) +{ + return false; /* XXX */ +} diff --git a/arch/aarch64/preboot.S b/arch/aarch64/preboot.S new file mode 100644 index 000000000..036b1fca6 --- /dev/null +++ b/arch/aarch64/preboot.S @@ -0,0 +1,19 @@ +/* + * 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. + */ + +target = . + 0x10000 +elf_entry = 24 + target + +.text +.align 16 + +.globl prestart +prestart: // x4 = 0x40080000 set by qemu bootloader + adr x0, target /* elf header start */ + adr x1, elf_entry + ldr x2, [x1] // load entry point from ELF header + br x2 diff --git a/arch/aarch64/preboot.ld b/arch/aarch64/preboot.ld new file mode 100644 index 000000000..4ddca8ef1 --- /dev/null +++ b/arch/aarch64/preboot.ld @@ -0,0 +1,4 @@ +SECTIONS +{ + .text : { *(.text) } +} diff --git a/arch/aarch64/processor.hh b/arch/aarch64/processor.hh new file mode 100644 index 000000000..2646adb68 --- /dev/null +++ b/arch/aarch64/processor.hh @@ -0,0 +1,117 @@ +/* + * 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 AARCH64_PROCESSOR_HH +#define AARCH64_PROCESSOR_HH + +#include <osv/types.h> +#include <osv/debug.h> + +namespace processor { + +constexpr unsigned daif_i = 1 << 7; + +inline void wfi() +{ + asm volatile ("wfi" ::: "memory"); +} + +inline void irq_enable() +{ + asm volatile ("msr daifclr, #2; isb; " ::: "memory"); +} + +inline void irq_disable() +{ + asm volatile ("msr daifset, #2; isb; " ::: "memory"); +} + +__attribute__((no_instrument_function)) +inline void irq_disable_notrace(); + +inline void irq_disable_notrace() +{ + asm volatile ("msr daifset, #2; isb; " ::: "memory"); +} + +inline void wait_for_interrupt() { + irq_enable(); + wfi(); +} + +inline void halt_no_interrupts() { + irq_disable(); + while (1) { + wfi(); + } +} + +inline u64 ticks() +{ + static u64 i; + return ++i; +} + +struct fpu_state { + __uint128_t vregs[32]; + unsigned long fpsr; + unsigned long fpcr; +}; + +inline void fpu_state_save(fpu_state *s) +{ + debug_early_entry("fpu_state_save(s)"); + + asm volatile("stp q0, q1, %0" : "=Ump"(s->vregs[0]) :: "memory"); + asm volatile("stp q2, q3, %0" : "=Ump"(s->vregs[2]) :: "memory"); + asm volatile("stp q4, q5, %0" : "=Ump"(s->vregs[4]) :: "memory"); + asm volatile("stp q6, q7, %0" : "=Ump"(s->vregs[6]) :: "memory"); + asm volatile("stp q8, q9, %0" : "=Ump"(s->vregs[8]) :: "memory"); + asm volatile("stp q10, q11, %0" : "=Ump"(s->vregs[10]) :: "memory"); + asm volatile("stp q12, q13, %0" : "=Ump"(s->vregs[12]) :: "memory"); + asm volatile("stp q14, q15, %0" : "=Ump"(s->vregs[14]) :: "memory"); + asm volatile("stp q16, q17, %0" : "=Ump"(s->vregs[16]) :: "memory"); + asm volatile("stp q18, q19, %0" : "=Ump"(s->vregs[18]) :: "memory"); + asm volatile("stp q20, q21, %0" : "=Ump"(s->vregs[20]) :: "memory"); + asm volatile("stp q22, q23, %0" : "=Ump"(s->vregs[22]) :: "memory"); + asm volatile("stp q24, q25, %0" : "=Ump"(s->vregs[24]) :: "memory"); + asm volatile("stp q26, q27, %0" : "=Ump"(s->vregs[26]) :: "memory"); + asm volatile("stp q28, q29, %0" : "=Ump"(s->vregs[28]) :: "memory"); + asm volatile("stp q30, q31, %0" : "=Ump"(s->vregs[30]) :: "memory"); + + asm volatile("mrs %0, fpsr" : "=r"(s->fpsr) :: "memory"); + asm volatile("mrs %0, fpcr" : "=r"(s->fpcr) :: "memory"); +} + +inline void fpu_state_load(fpu_state *s) +{ + debug_early_entry("fpu_state_load(s)"); + + asm volatile("ldp q0, q1, %0" :: "Ump"(s->vregs[0]) : "q0", "q1"); + asm volatile("ldp q2, q3, %0" :: "Ump"(s->vregs[2]) : "q2", "q3"); + asm volatile("ldp q4, q5, %0" :: "Ump"(s->vregs[4]) : "q4", "q5"); + asm volatile("ldp q6, q7, %0" :: "Ump"(s->vregs[6]) : "q6", "q7"); + asm volatile("ldp q8, q9, %0" :: "Ump"(s->vregs[8]) : "q8", "q9"); + asm volatile("ldp q10, q11, %0" :: "Ump"(s->vregs[10]) : "q10", "q11"); + asm volatile("ldp q12, q13, %0" :: "Ump"(s->vregs[12]) : "q12", "q13"); + asm volatile("ldp q14, q15, %0" :: "Ump"(s->vregs[14]) : "q14", "q15"); + asm volatile("ldp q16, q17, %0" :: "Ump"(s->vregs[16]) : "q16", "q17"); + asm volatile("ldp q18, q19, %0" :: "Ump"(s->vregs[18]) : "q18", "q19"); + asm volatile("ldp q20, q21, %0" :: "Ump"(s->vregs[20]) : "q20", "q21"); + asm volatile("ldp q22, q23, %0" :: "Ump"(s->vregs[22]) : "q22", "q23"); + asm volatile("ldp q24, q25, %0" :: "Ump"(s->vregs[24]) : "q24", "q25"); + asm volatile("ldp q26, q27, %0" :: "Ump"(s->vregs[26]) : "q26", "q27"); + asm volatile("ldp q28, q29, %0" :: "Ump"(s->vregs[28]) : "q28", "q29"); + asm volatile("ldp q30, q31, %0" :: "Ump"(s->vregs[30]) : "q30", "q31"); + + asm volatile("msr fpsr, %0" :: "r"(s->fpsr) : "memory"); + asm volatile("msr fpcr, %0" :: "r"(s->fpcr) : "memory"); +} + +} + +#endif /* AARCH64_PROCESSOR_HH */ diff --git a/arch/aarch64/safe-ptr.hh b/arch/aarch64/safe-ptr.hh new file mode 100644 index 000000000..f6026e2e8 --- /dev/null +++ b/arch/aarch64/safe-ptr.hh @@ -0,0 +1,31 @@ +/* + * 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 SAFE_PTR_HH_ +#define SAFE_PTR_HH_ + +#include <osv/compiler.h> + +/* warning: not "safe" at all for now. */ + +template <typename T> +static inline bool +safe_load(const T* potentially_bad_pointer, T& data) +{ + data = *potentially_bad_pointer; + return true; +} + +template <typename T> +static inline bool +safe_store(const T* potentially_bad_pointer, const T& data) +{ + *potentially_bad_pointer = data; + return true; +} + +#endif /* SAFE_PTR_HH_ */ diff --git a/arch/aarch64/signal.cc b/arch/aarch64/signal.cc new file mode 100644 index 000000000..b9d0de30c --- /dev/null +++ b/arch/aarch64/signal.cc @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2013 Cloudius Systems, Ltd. + * + * 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. + */ + +#include <osv/align.hh> +#include "exceptions.hh" +#include <signal.h> +#include <stdlib.h> +#include <arch-cpu.hh> +#include <osv/debug.hh> + +namespace arch { + +struct signal_frame { + exception_frame state; + siginfo_t si; + struct sigaction sa; +}; + +} + +extern "C" { + void call_signal_handler(arch::signal_frame* frame); + void call_signal_handler_thunk(void); +} + +namespace arch { + +void build_signal_frame(exception_frame* ef, + const siginfo_t& si, + const struct sigaction& sa) +{ + void* sp = reinterpret_cast<void*>(ef->sp); + sp -= sizeof(signal_frame); + sp = align_down(sp, 16); + signal_frame* frame = static_cast<signal_frame*>(sp); + frame->state = *ef; + frame->si = si; + frame->sa = sa; + ef->pc = reinterpret_cast<ulong>(call_signal_handler_thunk); + ef->sp = reinterpret_cast<ulong>(sp); +} + +} + +void call_signal_handler(arch::signal_frame* frame) +{ + processor::halt_no_interrupts(); +} diff --git a/arch/aarch64/smp.cc b/arch/aarch64/smp.cc new file mode 100644 index 000000000..3236ca027 --- /dev/null +++ b/arch/aarch64/smp.cc @@ -0,0 +1,29 @@ +/* + * 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. + */ + +#include <osv/debug.h> +#include <osv/sched.hh> +#include <osv/prio.hh> + +volatile unsigned smp_processors = 1; + +sched::cpu* smp_initial_find_current_cpu() +{ + for (auto c : sched::cpus) { + /* just return the single cpu we have for now */ + return c; + } + abort(); +} + +void __attribute__((constructor(init_prio::sched))) smp_init() +{ + auto c = new sched::cpu(0); + c->arch.gic_id = 0; + sched::cpus.push_back(c); + sched::current_cpu = sched::cpus[0]; +} diff --git a/arch/aarch64/smp.hh b/arch/aarch64/smp.hh new file mode 100644 index 000000000..8b00230a7 --- /dev/null +++ b/arch/aarch64/smp.hh @@ -0,0 +1,15 @@ +/* + * 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 ARCH_SMP_HH +#define ARCH_SMP_HH + +#include <osv/sched.hh> + +sched::cpu* smp_initial_find_current_cpu(); + +#endif /* ARCH_SMP_HH_ */ diff --git a/arch/aarch64/string.cc b/arch/aarch64/string.cc new file mode 100644 index 000000000..cd842d87f --- /dev/null +++ b/arch/aarch64/string.cc @@ -0,0 +1,35 @@ +/* + * 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. + */ + +#include <bits/alltypes.h> +#include <osv/string.h> + +extern "C" +void *memcpy_base(void *__restrict dest, const void *__restrict src, size_t n); +extern "C" +void *memset_base(void *__restrict dest, int c, size_t n); +extern "C" +void *memcpy_base_backwards(void *__restrict dest, const void *__restrict src, size_t n); + + +extern "C" +void *memcpy(void *__restrict dest, const void *__restrict src, size_t n) +{ + return memcpy_base(dest, src, n); +} + +extern "C" +void *memcpy_backwards(void *__restrict dest, const void *__restrict src, size_t n) +{ + return memcpy_base_backwards(dest, src, n); +} + +extern "C" +void *memset(void *__restrict dest, int c, size_t n) +{ + return memset_base(dest, c, n); +} -- GitLab