Skip to content

Instantly share code, notes, and snippets.

@nuta
Created June 5, 2020 03:07
Show Gist options
  • Save nuta/6d636d2a5ca76fc77f0a433e6dabfe37 to your computer and use it in GitHub Desktop.
Save nuta/6d636d2a5ca76fc77f0a433e6dabfe37 to your computer and use it in GitHub Desktop.
diff --git a/Kconfig b/Kconfig
index 30b56ec..46efaac 100644
--- a/Kconfig
+++ b/Kconfig
@@ -4,6 +4,8 @@ choice
prompt "Target CPU architecture"
config ARCH_X64
bool "x86_64"
+ config ARCH_ARM64
+ bool "Raspberry Pi 3 (AArch64)"
config ARCH_ARM
bool "micro:bit (ARM)"
endchoice
diff --git a/kernel/arch/arm64/Kconfig b/kernel/arch/arm64/Kconfig
new file mode 100644
index 0000000..1da9eb2
--- /dev/null
+++ b/kernel/arch/arm64/Kconfig
@@ -0,0 +1,8 @@
+menu "ARM64 Options"
+ depends on ARCH_ARM64
+
+ config ARCH
+ string
+ default "arm64"
+
+endmenu
diff --git a/kernel/arch/arm64/arch.h b/kernel/arch/arm64/arch.h
new file mode 100644
index 0000000..26b3778
--- /dev/null
+++ b/kernel/arch/arm64/arch.h
@@ -0,0 +1,52 @@
+#ifndef __ARCH_H__
+#define __ARCH_H__
+
+#include <types.h>
+
+#define TICK_HZ 1000
+#define IRQ_MAX 32
+#define STRAIGHT_MAP_ADDR 0 // Unused.
+#define STRAIGHT_MAP_END 0 // Unused.
+
+struct vm {
+};
+
+struct arch_task {
+ void *stack_bottom;
+ vaddr_t stack;
+};
+
+static inline void *from_paddr(paddr_t addr) {
+ return (void *) addr;
+}
+
+static inline paddr_t into_paddr(void *addr) {
+ return (vaddr_t) addr;
+}
+
+static inline bool is_kernel_addr_range(vaddr_t base, size_t len) {
+ return false;
+}
+
+static inline bool is_kernel_paddr(paddr_t paddr) {
+ return false;
+}
+
+static inline int mp_self(void) {
+ return 0;
+}
+
+static inline bool mp_is_bsp(void) {
+ return mp_self() == 0;
+}
+
+
+struct arch_cpuvar {
+};
+
+extern struct cpuvar cpuvar;
+static inline struct cpuvar *get_cpuvar(void) {
+ return &cpuvar;
+}
+
+#endif
diff --git a/kernel/arch/arm64/boot.S b/kernel/arch/arm64/boot.S
new file mode 100644
index 0000000..61cc844
--- /dev/null
+++ b/kernel/arch/arm64/boot.S
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 bzt (bztsrc@github)
+ *
+ * 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.
+ *
+ */
+
+.section ".boot", "ax"
+.global boot
+boot:
+ // read cpu id, stop slave cores
+ mrs x1, mpidr_el1
+ and x1, x1, #3
+ cbz x1, 2f
+ // cpu id > 0, stop
+1: wfe
+ b 1b
+2: // cpu id == 0
+
+ // set stack before our code
+ ldr x1, =__stack
+ mov sp, x1
+
+3:
+ bl arm64_init
+ b 3b
+
+.rodata
+.align 12 // 2^12 = 4096
+.global __bootelf
+__bootelf:
+ .incbin BOOTELF_PATH
+.align 12 // 2^12 = 4096
diff --git a/kernel/arch/arm64/build.mk b/kernel/arch/arm64/build.mk
new file mode 100644
index 0000000..548b426
--- /dev/null
+++ b/kernel/arch/arm64/build.mk
@@ -0,0 +1,20 @@
+obj-y += boot.o init.o vm.o mp.o task.o switch.o peripherals.o interrupt.o
+
+QEMU ?= qemu-system-aarch64
+
+CFLAGS += --target=aarch64-none-eabi -mcpu=cortex-a53
+LDFLAGS +=
+
+QEMUFLAGS += -M raspi3 -serial mon:stdio
+QEMUFLAGS += $(if $(GUI),,-nographic)
+QEMUFLAGS += $(if $(GDB),-S -s,)
+
+.PHONY: run
+run: $(BUILD_DIR)/resea.hex
+ $(QEMU) $(QEMUFLAGS) -device loader,file=$<
+
+.PHONY: hex
+hex: $(BUILD_DIR)/resea.hex
+
+$(BUILD_DIR)/resea.hex: $(kernel_image)
+ $(OBJCOPY) -Oihex $< $@
diff --git a/kernel/arch/arm64/init.c b/kernel/arch/arm64/init.c
new file mode 100644
index 0000000..88375aa
--- /dev/null
+++ b/kernel/arch/arm64/init.c
@@ -0,0 +1,20 @@
+#include <types.h>
+#include <main.h>
+#include <printk.h>
+#include "peripherals.h"
+
+void arch_idle(void) {
+ while (true) {
+ __asm__ __volatile__("wfi");
+ }
+}
+
+void arm64_init(void) {
+ arm_peripherals_init();
+ kmain();
+
+ PANIC("kmain returned");
+ for (;;) {
+ halt();
+ }
+}
diff --git a/kernel/arch/arm64/interrupt.c b/kernel/arch/arm64/interrupt.c
new file mode 100644
index 0000000..228d12d
--- /dev/null
+++ b/kernel/arch/arm64/interrupt.c
@@ -0,0 +1,26 @@
+#include <types.h>
+#include <task.h>
+#include <printk.h>
+
+void nmi_handler(void) {
+ PANIC("hard reset");
+}
+
+void hard_reset_handler(void) {
+ PANIC("hard reset");
+}
+void unexpected_handler(void) {
+ PANIC("unexpected exception");
+}
+
+void irq_handler(void) {
+// handle_irq(irq);
+}
+
+void arch_enable_irq(unsigned irq){
+ // TODO:
+}
+
+void arch_disable_irq(unsigned irq) {
+ // TODO:
+}
diff --git a/kernel/arch/arm64/kernel.ld b/kernel/arch/arm64/kernel.ld
new file mode 100644
index 0000000..273b999
--- /dev/null
+++ b/kernel/arch/arm64/kernel.ld
@@ -0,0 +1,76 @@
+OUTPUT_FORMAT("elf64-x86-64");
+ENTRY(boot);
+
+/* LMA_OFFSET = 0xffff800000000000; */
+LMA_OFFSET = 0;
+KERNEL_BOOT_ADDR = 0x80000;
+KERNEL_BASE_ADDR = 0x80000;
+/* KERNEL_BASE_ADDR = 0xffff800000100000; */
+
+PHDRS {
+ boot PT_LOAD FLAGS(5); /* flags = rx */
+ text PT_LOAD FLAGS(5); /* flags = rx */
+ data PT_LOAD FLAGS(6); /* flags = rw */
+}
+
+SECTIONS {
+ . = KERNEL_BOOT_ADDR;
+ __kernel_image = .; /* paddr_t */
+ .boot : AT(KERNEL_BOOT_ADDR) {
+ KEEP(*(.boot));
+ } :boot
+
+ . = KERNEL_BASE_ADDR + SIZEOF(.boot);
+
+ .text : AT(ADDR(.text) - LMA_OFFSET) ALIGN(8) {
+ *(.text);
+ *(.text.*);
+ } :text
+
+ .rodata : AT(ADDR(.rodata) - LMA_OFFSET) ALIGN(8) {
+ *(.rodata);
+ *(.rodata.*);
+ } :text
+
+ .data : AT(ADDR(.data) - LMA_OFFSET) ALIGN(8) {
+ *(.data);
+ *(.data.*);
+ } :data
+
+ .bss : AT(ADDR(.bss) - LMA_OFFSET) ALIGN(8) {
+ __bss = .;
+ *(.bss);
+ *(.bss.*);
+ __bss_end = .;
+ } :data
+
+ . = ALIGN(4096);
+ __kernel_image_end = . - KERNEL_BASE_ADDR + KERNEL_BOOT_ADDR; /* paddr_t */
+
+ . = 0x1000000;
+ __kernel_data = .; /* paddr_t */
+
+ /* CPU variables and boot stacks (paddr_t). */
+ . = ALIGN(4096);
+ __cpuvar_base = .;
+ . += 0x4000 * 16; /* CPUVAR_SIZE_MAX * CPU_NUM_MAX */
+ __boot_stack_base = .;
+ . += 0x1000 * 16; /* PAGE_SIZE * CPU_NUM_MAX */
+
+ /* Kernel Heap (vaddr_t). */
+ . = ALIGN(4096);
+ . += LMA_OFFSET;
+ __kernel_heap = .;
+ . = LMA_OFFSET + 0x3000000;
+ __kernel_heap_end = .;
+
+ . = ALIGN(4096);
+ __kernel_data_end = . - LMA_OFFSET; /* paddr_t */
+
+ /* A temporary page used internally by kernel (virtual address). */
+ __temp_page = 0xffff0000;
+
+ /DISCARD/ :{
+ *(*.eh_frame);
+ }
+}
diff --git a/kernel/arch/arm64/mp.c b/kernel/arch/arm64/mp.c
new file mode 100644
index 0000000..5a10f99
--- /dev/null
+++ b/kernel/arch/arm64/mp.c
@@ -0,0 +1,21 @@
+#include <task.h>
+
+struct cpuvar cpuvar;
+
+void halt(void) {
+ while (true) {
+ __asm__ __volatile__("wfi");
+ }
+}
+
+void panic_lock(void) {
+ // Do nothing: we don't support multiprocessors.
+}
+
+void mp_start(void) {
+ // Do nothing: we don't support multiprocessors.
+}
+
+void mp_reschedule(void) {
+ // Do nothing: we don't support multiprocessors.
+}
diff --git a/kernel/arch/arm64/peripherals.c b/kernel/arch/arm64/peripherals.c
new file mode 100644
index 0000000..cc2647c
--- /dev/null
+++ b/kernel/arch/arm64/peripherals.c
@@ -0,0 +1,137 @@
+#include <types.h>
+#include <printk.h>
+#include "peripherals.h"
+
+
+/*
+ * Copyright (C) 2018 bzt (bztsrc@github)
+ *
+ * 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.
+ *
+ */
+
+#define MMIO_BASE 0x3F000000
+
+#define GPFSEL0 ((volatile unsigned int*)(MMIO_BASE+0x00200000))
+#define GPFSEL1 ((volatile unsigned int*)(MMIO_BASE+0x00200004))
+#define GPFSEL2 ((volatile unsigned int*)(MMIO_BASE+0x00200008))
+#define GPFSEL3 ((volatile unsigned int*)(MMIO_BASE+0x0020000C))
+#define GPFSEL4 ((volatile unsigned int*)(MMIO_BASE+0x00200010))
+#define GPFSEL5 ((volatile unsigned int*)(MMIO_BASE+0x00200014))
+#define GPSET0 ((volatile unsigned int*)(MMIO_BASE+0x0020001C))
+#define GPSET1 ((volatile unsigned int*)(MMIO_BASE+0x00200020))
+#define GPCLR0 ((volatile unsigned int*)(MMIO_BASE+0x00200028))
+#define GPLEV0 ((volatile unsigned int*)(MMIO_BASE+0x00200034))
+#define GPLEV1 ((volatile unsigned int*)(MMIO_BASE+0x00200038))
+#define GPEDS0 ((volatile unsigned int*)(MMIO_BASE+0x00200040))
+#define GPEDS1 ((volatile unsigned int*)(MMIO_BASE+0x00200044))
+#define GPHEN0 ((volatile unsigned int*)(MMIO_BASE+0x00200064))
+#define GPHEN1 ((volatile unsigned int*)(MMIO_BASE+0x00200068))
+#define GPPUD ((volatile unsigned int*)(MMIO_BASE+0x00200094))
+#define GPPUDCLK0 ((volatile unsigned int*)(MMIO_BASE+0x00200098))
+#define GPPUDCLK1 ((volatile unsigned int*)(MMIO_BASE+0x0020009C))
+
+/* Auxilary mini UART registers */
+#define AUX_ENABLE ((volatile unsigned int*)(MMIO_BASE+0x00215004))
+#define AUX_MU_IO ((volatile unsigned int*)(MMIO_BASE+0x00215040))
+#define AUX_MU_IER ((volatile unsigned int*)(MMIO_BASE+0x00215044))
+#define AUX_MU_IIR ((volatile unsigned int*)(MMIO_BASE+0x00215048))
+#define AUX_MU_LCR ((volatile unsigned int*)(MMIO_BASE+0x0021504C))
+#define AUX_MU_MCR ((volatile unsigned int*)(MMIO_BASE+0x00215050))
+#define AUX_MU_LSR ((volatile unsigned int*)(MMIO_BASE+0x00215054))
+#define AUX_MU_MSR ((volatile unsigned int*)(MMIO_BASE+0x00215058))
+#define AUX_MU_SCRATCH ((volatile unsigned int*)(MMIO_BASE+0x0021505C))
+#define AUX_MU_CNTL ((volatile unsigned int*)(MMIO_BASE+0x00215060))
+#define AUX_MU_STAT ((volatile unsigned int*)(MMIO_BASE+0x00215064))
+#define AUX_MU_BAUD ((volatile unsigned int*)(MMIO_BASE+0x00215068))
+
+/**
+ * Set baud rate and characteristics (115200 8N1) and map to GPIO
+ */
+void uart_init()
+{
+ register unsigned int r;
+
+ /* initialize UART */
+ *AUX_ENABLE |=1; // enable UART1, AUX mini uart
+ *AUX_MU_CNTL = 0;
+ *AUX_MU_LCR = 3; // 8 bits
+ *AUX_MU_MCR = 0;
+ *AUX_MU_IER = 0;
+ *AUX_MU_IIR = 0xc6; // disable interrupts
+ *AUX_MU_BAUD = 270; // 115200 baud
+ /* map UART1 to GPIO pins */
+ r=*GPFSEL1;
+ r&=~((7<<12)|(7<<15)); // gpio14, gpio15
+ r|=(2<<12)|(2<<15); // alt5
+ *GPFSEL1 = r;
+ *GPPUD = 0; // enable pins 14 and 15
+ r=150; while(r--) { __asm__ __volatile__("nop"); }
+ *GPPUDCLK0 = (1<<14)|(1<<15);
+ r=150; while(r--) { __asm__ __volatile__("nop"); }
+ *GPPUDCLK0 = 0; // flush GPIO setup
+ *AUX_MU_CNTL = 3; // enable Tx, Rx
+}
+
+/**
+ * Send a character
+ */
+void uart_send(unsigned int c) {
+ /* wait until we can send */
+ do{__asm__ __volatile__("nop");}while(!(*AUX_MU_LSR&0x20));
+ /* write the character to the buffer */
+ *AUX_MU_IO=c;
+}
+
+/**
+ * Receive a character
+ */
+char uart_getc() {
+ char r;
+ /* wait until something is in the buffer */
+ do{__asm__ __volatile__("nop");}while(!(*AUX_MU_LSR&0x01));
+ /* read it and return */
+ r=(char)(*AUX_MU_IO);
+ /* convert carrige return to newline */
+ return r=='\r'?'\n':r;
+}
+
+
+
+static inline uint32_t mmio_read(vaddr_t addr) {
+ return *((volatile uint32_t *) addr);
+}
+
+static inline void mmio_write(vaddr_t addr, uint32_t value) {
+ *((volatile uint32_t *) addr) = value;
+}
+
+void arch_printchar(char ch) {
+ uart_send(ch);
+}
+
+char kdebug_readchar(void) {
+ return '\0';
+}
+
+void arm_peripherals_init(void) {
+ uart_init();
+}
diff --git a/kernel/arch/arm64/peripherals.h b/kernel/arch/arm64/peripherals.h
new file mode 100644
index 0000000..fcfa347
--- /dev/null
+++ b/kernel/arch/arm64/peripherals.h
@@ -0,0 +1,6 @@
+#ifndef __ARM_PERIPHERALS_H__
+#define __ARM_PERIPHERALS_H__
+
+void arm_peripherals_init(void);
+
+#endif
diff --git a/kernel/arch/arm64/switch.S b/kernel/arch/arm64/switch.S
new file mode 100644
index 0000000..8ef7768
--- /dev/null
+++ b/kernel/arch/arm64/switch.S
@@ -0,0 +1,10 @@
+.text
+
+// void arm_task_switch(vaddr_t *prev_sp, vaddr_t next_sp);
+.global arm_task_switch
+arm_task_switch:
+
+
+.global arm_start_task
+arm_start_task:
+// bl stack_set_canary
diff --git a/kernel/arch/arm64/task.c b/kernel/arch/arm64/task.c
new file mode 100644
index 0000000..9bdcc3d
--- /dev/null
+++ b/kernel/arch/arm64/task.c
@@ -0,0 +1,55 @@
+#include <syscall.h>
+#include <cstring.h>
+#include <main.h>
+#include <task.h>
+#include <memory.h>
+
+#define STACK_SIZE 1024
+
+void arm_start_task(void);
+
+// Prepare the initial stack for arm_task_switch().
+static void init_stack(struct task *task, vaddr_t pc) {
+ uint32_t *sp = (uint32_t *) ((vaddr_t) task->arch.stack_bottom + STACK_SIZE);
+ // Fill the exception stack frame. After the first context switch, the CPU
+ // always runs the kernel code in the handler mode because of exceptions
+ // (e.g. timer interrupts and system calls).
+ *--sp = 1 << 24; // psr
+ *--sp = pc | 1; // pc
+ *--sp = 0; // lr
+ *--sp = 0; // r12
+ *--sp = 0; // r3
+ *--sp = 0; // r2
+ *--sp = 0; // r1
+ *--sp = 0; // r0
+ *--sp = 0xfffffff9; // return from exception
+
+ *--sp = (vaddr_t) arm_start_task; // Task starts here.
+ int num_zeroed_regs = 8; // r4-r11
+ for (int i = 0; i < num_zeroed_regs; i++) {
+ *--sp = 0;
+ }
+
+ task->arch.stack = (vaddr_t) sp;
+}
+
+error_t arch_task_create(struct task *task, vaddr_t pc) {
+ void *stack = kmalloc(STACK_SIZE);
+ if (!stack) {
+ return ERR_NO_MEMORY;
+ }
+
+ task->arch.stack_bottom = stack;
+ init_stack(task, pc);
+ return OK;
+}
+
+void arch_task_destroy(struct task *task) {
+ kfree((void *) task->arch.stack_bottom);
+}
+
+void arm_task_switch(vaddr_t *prev_sp, vaddr_t next_sp);
+
+void arch_task_switch(struct task *prev, struct task *next) {
+ arm_task_switch(&prev->arch.stack, next->arch.stack);
+}
diff --git a/kernel/arch/arm64/vm.c b/kernel/arch/arm64/vm.c
new file mode 100644
index 0000000..0bf321b
--- /dev/null
+++ b/kernel/arch/arm64/vm.c
@@ -0,0 +1,38 @@
+#include <memory.h>
+#include <syscall.h>
+#include <cstring.h>
+
+int __temp_page; // unused as we don't use virtual memory
+
+error_t vm_create(struct vm *vm) {
+ // Do nothing: we don't support virtual memory.
+ return OK;
+}
+
+void vm_destroy(struct vm *vm) {
+ // Do nothing: we don't support virtual memory.
+}
+
+error_t vm_link(struct vm *vm, vaddr_t vaddr, paddr_t paddr,
+ pageattrs_t attrs) {
+ // Do nothing: we don't support virtual memory.
+ return OK;
+}
+
+void vm_unlink(struct vm *vm, vaddr_t vaddr) {
+ // Do nothing: we don't support virtual memory.
+}
+
+paddr_t vm_resolve(struct vm *vm, vaddr_t vaddr) {
+ return vaddr;
+}
+
+void arch_memcpy_from_user(void *dst, userptr_t src, size_t len) {
+ memcpy(dst, (void *) src, len);
+}
+void arch_memcpy_to_user(userptr_t dst, const void *src, size_t len) {
+ memcpy((void *) dst, src, len);
+}
+void arch_strncpy_from_user(char *dst, userptr_t src, size_t max_len) {
+ strncpy(dst, (char *) src, max_len);
+}
diff --git a/libs/common/arch/arm64/arch_types.h b/libs/common/arch/arm64/arch_types.h
new file mode 100644
index 0000000..3320075
--- /dev/null
+++ b/libs/common/arch/arm64/arch_types.h
@@ -0,0 +1,25 @@
+#ifndef __ARCH_TYPES_H__
+#define __ARCH_TYPES_H__
+
+typedef uint32_t pageattrs_t;
+typedef uint64_t size_t;
+typedef int64_t intmax_t;
+typedef uint64_t uintmax_t;
+typedef uint64_t paddr_t;
+typedef uint64_t vaddr_t;
+typedef uint64_t uintptr_t;
+
+#define PAGE_SIZE 4096
+#define PAGE_PRESENT (1 << 0)
+#define PAGE_WRITABLE (1 << 1)
+#define PAGE_USER (1 << 2)
+
+typedef uint32_t pagefault_t;
+#define PF_PRESENT (1 << 0)
+#define PF_WRITE (1 << 1)
+#define PF_USER (1 << 2)
+
+typedef struct {
+} trap_frame_t;
+
+#endif
diff --git a/libs/common/arch/arm64/build.mk b/libs/common/arch/arm64/build.mk
new file mode 100644
index 0000000..e69de29
diff --git a/libs/resea/arch/arm64/arch/io.h b/libs/resea/arch/arm64/arch/io.h
new file mode 100644
index 0000000..8bf41a8
--- /dev/null
+++ b/libs/resea/arch/arm64/arch/io.h
@@ -0,0 +1,6 @@
+#ifndef __RESEA_ARCH_IO_H__
+#define __RESEA_ARCH_IO_H__
+
+// TODO:
+
+#endif
diff --git a/libs/resea/arch/arm64/arch/syscall.h b/libs/resea/arch/arm64/arch/syscall.h
new file mode 100644
index 0000000..3b9733d
--- /dev/null
+++ b/libs/resea/arch/arm64/arch/syscall.h
@@ -0,0 +1,26 @@
+#ifndef __ARCH_SYSCALL_H__
+#define __ARCH_SYSCALL_H__
+
+#include <types.h>
+
+static inline long syscall(int n, long a1, long a2, long a3, long a4, long a5) {
+ register long r0 __asm__("r0") = n;
+ register long r1 __asm__("r1") = a1;
+ register long r2 __asm__("r2") = a2;
+ register long r3 __asm__("r3") = a3;
+ register long r4 __asm__("r4") = a4;
+ register long r5 __asm__("r5") = a5;
+ register long r6 __asm__("r6") = r6;
+
+ /* FIXME:
+ __asm__ __volatile__(
+ "svc 0"
+ : "=r"(r0), "=r"(r6)
+ : "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5)
+ : "ip", "memory");
+ */
+
+ return r6; // FIXME:
+}
+
+#endif
diff --git a/libs/resea/arch/arm64/build.mk b/libs/resea/arch/arm64/build.mk
new file mode 100644
index 0000000..f9151d2
--- /dev/null
+++ b/libs/resea/arch/arm64/build.mk
@@ -0,0 +1 @@
+obj-y += start.o
diff --git a/libs/resea/arch/arm64/start.S b/libs/resea/arch/arm64/start.S
new file mode 100644
index 0000000..b112ce0
--- /dev/null
+++ b/libs/resea/arch/arm64/start.S
@@ -0,0 +1,17 @@
+.text
+.global _start
+_start:
+// TODO: set sp
+
+ // Initialize the user library.
+// bl resea_init
+
+ // Call main().
+// bl main
+
+ // main() has returned. Exit the current task.
+// bl task_exit
+
+.global halt
+halt:
+ b halt
diff --git a/libs/resea/arch/arm64/user.ld b/libs/resea/arch/arm64/user.ld
new file mode 100644
index 0000000..099698e
--- /dev/null
+++ b/libs/resea/arch/arm64/user.ld
@@ -0,0 +1,58 @@
+PHDRS {
+ text PT_LOAD;
+ data PT_LOAD;
+ bss PT_LOAD;
+}
+
+SECTIONS {
+ /* XXX: For simplicity of the implementation, kernel's ELF loader assumes
+ the address and the length of program headers are aligned to 4096
+ (PAGE_SIZE). */
+ . = 0x100000;
+
+ .text :{
+ *(.text*)
+ } :text
+
+ .rodata :{
+ *(.rodata*)
+ . = ALIGN(4096); // See the XXX comment above.
+ } :text
+
+ .data :{
+ *(.data*)
+ . = ALIGN(4096); // See the XXX comment above.
+ } :data
+
+ __zeroed_pages = .;
+
+ .bss :{
+ __bss = .;
+ *(.bss*);
+ __bss_end = .;
+
+ . = ALIGN(4);
+ __heap = .;
+ . += 4096;
+ . = ALIGN(4096); // See the XXX comment above.
+ __heap_end = .;
+ } :bss
+
+ . = ALIGN(16);
+ __stack = .;
+ . += 0x4000;
+ __stack_end = .;
+
+ . = ALIGN(16);
+ __heap = .;
+ . = 0x05000000;
+ __heap_end = .;
+
+ __free_vaddr = .;
+ . = 0x0a000000;
+ __free_vaddr_end = .;
+
+ /DISCARD/ :{
+ *(.ARM.exidx)
+ }
+}
diff --git a/servers/bootstrap/bootfs.S b/servers/bootstrap/bootfs.S
index 355867d..de424a1 100644
--- a/servers/bootstrap/bootfs.S
+++ b/servers/bootstrap/bootfs.S
@@ -1,5 +1,13 @@
+#include <config.h>
+
.rodata
+#ifdef CONFIG_ARCH_ARM64
+// FIXME: I dunno why but in arm64, .align directive takes a exponent.
+.align 12
+#else
.align 4096
+#endif
+
.global __bootfs, __bootfs_end
__bootfs:
.incbin BOOTFS_PATH
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment